File size: 3,455 Bytes
4415e0c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# client.js (modified JavaScript)
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
const callBtn = document.getElementById('callBtn');
const endCallBtn = document.getElementById('endCallBtn');
// ... other DOM elements

let peerConnection;
let localStream;
let socket;
let roomId;
let clientId;

async function init() {
    try {
        localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
        localVideo.srcObject = localStream;
        roomId = uuid.v4(); // Generate a unique room ID
        clientId = uuid.v4(); // Generate a unique client ID
        socket = new WebSocket(`ws://localhost:8000/ws/${roomId}/${clientId}`); // Connect to the WebSocket server
        socket.onmessage = handleSocketMessage;
        socket.onopen = startCall; // Start call after socket opens.
        setupEventListeners();
        optimizerPanel.classList.remove('hidden');
        applyBandwidthPreset(currentBandwidthPreset);
    } catch (error) {
        console.error('Initialization error:', error);
    }
}

async function startCall() {
    if (!localStream) {
        alert('Please allow camera and microphone access first.');
        return;
    }

    connectionModal.classList.remove('hidden');
    simulateConnectionProgress();

    try {
        peerConnection = new RTCPeerConnection({
            iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
        });

        peerConnection.onicecandidate = handleICECandidate;
        peerConnection.ontrack = handleTrack;

        localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));

        const offer = await peerConnection.createOffer();
        await peerConnection.setLocalDescription(offer);

        socket.send(JSON.stringify({ type: 'offer', sdp: offer.sdp })); // Send the offer via WebSocket

    } catch (error) {
        console.error('Error starting call:', error);
        connectionModal.classList.add('hidden');
        alert('Failed to start call. Please try again.');
    }
}

function handleSocketMessage(event) {
    const data = JSON.parse(event.data);

    if (data.type === 'offer' || data.type === 'answer') {
        peerConnection.setRemoteDescription(new RTCSessionDescription(data));
        if (data.type === 'offer') {
            peerConnection.createAnswer()
                .then(answer => peerConnection.setLocalDescription(answer))
                .then(() => socket.send(JSON.stringify({ type: 'answer', sdp: peerConnection.localDescription.sdp })));
        }
    } else if (data.type === 'candidate') {
        peerConnection.addIceCandidate(new RTCIceCandidate(data.candidate));
    }
    // ... rest of the socket message handling
}

function handleICECandidate(event) {
    if (event.candidate) {
        socket.send(JSON.stringify({ type: 'candidate', candidate: event.candidate })); // Send ICE candidate via WebSocket
    }
}

function handleTrack(event) {
    remoteVideo.srcObject = event.streams[0];
    connectionStatus.textContent = 'Connected';
    connectionStatus.className = 'font-medium text-green-400';
    bandwidthIndicator.classList.remove('hidden');
    updateBandwidthDisplay();
    callBtn.classList.add('hidden');
    endCallBtn.classList.remove('hidden');
    connectionModal.classList.add('hidden');
    isCallActive = true;
}

// ... rest of the JavaScript code (toggleVideo, toggleAudio, etc.)