mirror of
https://github.com/AlexandreRouma/wiscast.git
synced 2026-04-20 08:22:42 +00:00
progress
This commit is contained in:
40
display.go
40
display.go
@@ -11,18 +11,21 @@ import "github.com/gorilla/websocket"
|
|||||||
// Display instance
|
// Display instance
|
||||||
type Display struct {
|
type Display struct {
|
||||||
// WebSocket used to communicate with the display
|
// WebSocket used to communicate with the display
|
||||||
sock *websocket.Conn
|
sock *websocket.Conn;
|
||||||
sockSendMtx sync.Mutex
|
sockSendMtx sync.Mutex;
|
||||||
|
|
||||||
|
// User mutex
|
||||||
|
userMtx sync.Mutex;
|
||||||
|
|
||||||
// User currently connected to the display
|
// User currently connected to the display
|
||||||
user *User
|
user *User;
|
||||||
|
|
||||||
// One-time-pass currently shown on the display
|
// One-time-pass currently shown on the display
|
||||||
otpMtx sync.Mutex
|
otpMtx sync.Mutex;
|
||||||
otp string
|
otp string;
|
||||||
|
|
||||||
// Channel to pass the answer from the display coroutine to the user couroutine
|
// Channel to pass the answer from the display coroutine to the user couroutine
|
||||||
answerCh chan string
|
answerCh chan string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to flush channels
|
// Helper function to flush channels
|
||||||
@@ -50,7 +53,7 @@ func chReadTimeout(ch *chan string, timeoutMS int) (string, error) {
|
|||||||
return data, nil
|
return data, nil
|
||||||
|
|
||||||
// If no data has been received and the timeout is reached, return an error
|
// If no data has been received and the timeout is reached, return an error
|
||||||
case <-time.After(timeoutMS * time.Millisecond):
|
case <-time.After(time.Millisecond * time.Duration(timeoutMS)):
|
||||||
return "", errors.New("timeout")
|
return "", errors.New("timeout")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,7 +209,28 @@ func displayHandler(sock *websocket.Conn, dispID string, otp string) {
|
|||||||
disp.answerCh <- answer
|
disp.answerCh <- answer
|
||||||
|
|
||||||
case "ice-candidate":
|
case "ice-candidate":
|
||||||
// TODO
|
// Check that the message contains an ice candidate
|
||||||
|
candidate, valid := msg.arguments["candidate"].(string)
|
||||||
|
if (!valid) { break; }
|
||||||
|
|
||||||
|
// Acquire the user's display pointer
|
||||||
|
disp.userMtx.Lock();
|
||||||
|
|
||||||
|
// Check that a user is connected to a display
|
||||||
|
if (disp.user == nil) {
|
||||||
|
// Release the user's display pointer
|
||||||
|
disp.userMtx.Unlock();
|
||||||
|
|
||||||
|
// Send back an error
|
||||||
|
sendErrorMessage(sock, http.StatusForbidden);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the ice candidtate to the display
|
||||||
|
disp.user.iceCandidate(candidate);
|
||||||
|
|
||||||
|
// Release the user's display pointer
|
||||||
|
disp.userMtx.Unlock();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Give up
|
// Give up
|
||||||
|
|||||||
20
user.go
20
user.go
@@ -10,6 +10,7 @@ import "github.com/gorilla/websocket"
|
|||||||
type User struct {
|
type User struct {
|
||||||
// WebSocket used to communicate with the user
|
// WebSocket used to communicate with the user
|
||||||
sock *websocket.Conn;
|
sock *websocket.Conn;
|
||||||
|
sockSendMtx sync.Mutex;
|
||||||
|
|
||||||
// Display mutex
|
// Display mutex
|
||||||
displayMtx sync.Mutex;
|
displayMtx sync.Mutex;
|
||||||
@@ -18,6 +19,23 @@ type User struct {
|
|||||||
display *Display;
|
display *Display;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send an ICE candiate to the user
|
||||||
|
func (this *User) iceCandidate(candidate string) {
|
||||||
|
// Acquire the sending mutex
|
||||||
|
this.sockSendMtx.Lock()
|
||||||
|
|
||||||
|
// Send the candidate
|
||||||
|
sendMessage(this.sock, Message{
|
||||||
|
mtype: "ice-candidate",
|
||||||
|
arguments: map[string]interface{}{
|
||||||
|
"candidate": candidate,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Release the sending mutex
|
||||||
|
this.sockSendMtx.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// Connection handler for users
|
// Connection handler for users
|
||||||
func userHandler(sock *websocket.Conn) {
|
func userHandler(sock *websocket.Conn) {
|
||||||
// Initialize the user instance
|
// Initialize the user instance
|
||||||
@@ -170,8 +188,6 @@ func userHandler(sock *websocket.Conn) {
|
|||||||
// Send the ice candidtate to the display
|
// Send the ice candidtate to the display
|
||||||
user.display.iceCandidate(candidate);
|
user.display.iceCandidate(candidate);
|
||||||
|
|
||||||
// TODO: Check error
|
|
||||||
|
|
||||||
// Release the user's display pointer
|
// Release the user's display pointer
|
||||||
user.displayMtx.Unlock();
|
user.displayMtx.Unlock();
|
||||||
|
|
||||||
|
|||||||
@@ -15,16 +15,16 @@
|
|||||||
<!-- Connection form -->
|
<!-- Connection form -->
|
||||||
<div id="connForm">
|
<div id="connForm">
|
||||||
<p class="TV">📺</p><br>
|
<p class="TV">📺</p><br>
|
||||||
<input type="text" id="dispName" placeholder="Display ID" required autocomplete="off" oninput="onDispNameChange()"><br><br>
|
<input type="text" id="dispName" placeholder="Display ID" required autocomplete="off"><br><br>
|
||||||
<input type="text" id="otp" placeholder="OTP" required autocomplete="off" oninput="onOTPChange()"><br><br>
|
<input type="text" id="otp" placeholder="OTP" required autocomplete="off"><br><br>
|
||||||
<button id="connect" onclick="connect()" disabled autocomplete="off">Connect</button>
|
<button id="connect" disabled autocomplete="off">Connect</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Streaming form -->
|
<!-- Streaming form -->
|
||||||
<div id="streamForm" hidden>
|
<div id="streamForm" hidden>
|
||||||
<h1>You are live!</h1>
|
<h1>You are live!</h1>
|
||||||
<video id="localPlayback" autoplay playsinline></video><br><br>
|
<video id="localPlayback" autoplay playsinline></video><br><br>
|
||||||
<button id="disconnect" onclick="disconnect()">Disconnect</button>
|
<button id="disconnect">Disconnect</button>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
@@ -4,37 +4,69 @@ let stream = null;
|
|||||||
let conn = null;
|
let conn = null;
|
||||||
|
|
||||||
// GUI Objects
|
// GUI Objects
|
||||||
let connForm = document.querySelector('#connForm');
|
let connForm = document.getElementById('connForm');
|
||||||
let dispNameTb = document.querySelector('#dispName');
|
let dispNameTb = document.getElementById('dispName');
|
||||||
let connBtn = document.querySelector('#connect');
|
let connBtn = document.getElementById('connect');
|
||||||
let pinValForm = document.querySelector('#pinValForm');
|
let pinValForm = document.getElementById('pinValForm');
|
||||||
let dispPINTb = document.querySelector('#dispPIN');
|
let dispPINTb = document.getElementById('dispPIN');
|
||||||
let validateBtn = document.querySelector('#validate');
|
let validateBtn = document.getElementById('validate');
|
||||||
let streamForm = document.querySelector('#streamForm');
|
let streamForm = document.getElementById('streamForm');
|
||||||
let locPlayback = document.querySelector('#localPlayback');
|
let locPlayback = document.getElementById('localPlayback');
|
||||||
|
|
||||||
// Connect to the server using WebSockets
|
// User API class
|
||||||
console.log('Connecting to websocket...')
|
class WisCastUserAPI {
|
||||||
sock = new WebSocket(`ws://${location.host}/sig`);
|
// Socket to the API endpoint
|
||||||
sock.addEventListener('open', async (event) => {
|
#sock;
|
||||||
console.log('Connected to websocket')
|
|
||||||
|
|
||||||
// // DEBUGGING ONLY
|
// Endpoint URL
|
||||||
// await sock.send(JSON.stringify({
|
#endpoint;
|
||||||
// type: 'init',
|
|
||||||
// pin: dispPINTb.value
|
|
||||||
// }))
|
|
||||||
|
|
||||||
await sock.send(JSON.stringify({
|
constructor(endpoint) {
|
||||||
type: 'init',
|
// Save the endpoint
|
||||||
clientType: 'user'
|
this.endpoint = endpoint;
|
||||||
}));
|
}
|
||||||
});
|
|
||||||
|
|
||||||
sock.addEventListener('message', (event) => {
|
// Connect to the API
|
||||||
console.log(event.data)
|
async connect() {
|
||||||
});
|
// Connect to the WebSocket endpoint
|
||||||
|
console.log('Connecting to the API...')
|
||||||
|
this.#sock = new WebSocket(endpoint);
|
||||||
|
|
||||||
sock.addEventListener('close', (event) => {
|
// Handle connection
|
||||||
console.log('Disconnected from websocket')
|
sock.addEventListener('open', this.#connectHandler);
|
||||||
});
|
|
||||||
|
// Handle messages
|
||||||
|
sock.addEventListener('message', this.#messageHandler);
|
||||||
|
|
||||||
|
// Handle disconnection
|
||||||
|
sock.addEventListener('close', this.#disconnectHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect to a display using its ID and OTP
|
||||||
|
async connectDisplay(dispID, OTP) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#connectHandler(event) {
|
||||||
|
console.log('Connected!')
|
||||||
|
}
|
||||||
|
|
||||||
|
#messageHandler(event) {
|
||||||
|
console.log(event.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#disconnectHandler(event) {
|
||||||
|
console.log('Disconnected :/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// Create the API connection
|
||||||
|
const api = new WisCastUserAPI(`ws://${location.host}/sig`);
|
||||||
|
|
||||||
|
// Connect to the server
|
||||||
|
await api.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the main function
|
||||||
|
main();
|
||||||
Reference in New Issue
Block a user