let PARSEC; let AUDIO; let DAEMON_WAITING = false; let PEER_ID_C; const PARSEC_ENV = { // user.bin bin_user_bin_get: function (asset_dir_c, session_id_c, size) { try { const cookies = document.cookie.split(';'); for (let x = 0; x < cookies.length; x++) { const cookie = cookies[x].trim(); const name = 'parsec_login='; if (cookie.indexOf(name) == 0) { const auth = JSON.parse(cookie.substring(name.length, cookie.length)); MTY_StrToC(auth['token'], session_id_c, size); return 0; } } } catch (e) { console.error(e); } return -1; }, bin_user_bin_set: function (asset_dir_c, session_id_c) { const session_id = MTY_StrToJS(session_id_c); const value = JSON.stringify({ 'token': session_id, 'userId': 0, }); const hostname = window.location.hostname.replace(/.*?\./, ''); const secure = window.location.protocol == 'https:'; document.cookie = 'parsec_login=' + value + ';domain=' + hostname + ';path=/;' + (secure ? 'secure' : '') + ';max-age=31536000;samesite=strict;'; }, bin_user_bin_delete: function (asset_dir_c) { const hostname = window.location.hostname.replace(/.*?\./, ''); document.cookie = 'parsec_login=;domain=' + hostname + ';path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT;'; }, // Audio control web_mute: function (muted) { AUDIO.muted = muted; }, // ws-api signal_set_peer_id: function (s, attempt_id, peer_id) { if (!PARSEC) return; PARSEC.setPeerID(MTY_StrToJS(attempt_id), MTY_StrToJS(peer_id)); }, signal_get_peer_id: function (s, attempt_id) { if (!PARSEC) return; const peer_id = PARSEC.getPeerID(MTY_StrToJS(attempt_id)); if (!PEER_ID_C) PEER_ID_C = MTY_Alloc(128); MTY_StrToC(peer_id, PEER_ID_C, 128); return PEER_ID_C; }, signal_client_cancel: function (s, ps) { if (!PARSEC) return; PARSEC.sendCancel(PARSEC.getAttemptID()); PARSEC_ENV.parsec_web_disconnect(); }, web_send_candex: function (attempt_id, ip, port, sync, fromStun, lan) { if (!PARSEC) return; PARSEC.sendCandidate(MTY_StrToJS(attempt_id), MTY_StrToJS(ip), port, sync, fromStun, lan); }, signal_host_allow_guest: function (s, ps, attempt_id, allow) { }, signal_host_stop: function (s, ps) { }, signal_send_conn_update: function (s, ps) { }, signal_host_set_permissions: function (s, ps, guest_id, perms) { }, signal_host_start: function (s, ps, mode, cfg, priv, session_id) { return -1; }, signal_host_set_config: function (s, ps, cfg, priv) { }, signal_client_connect: function (s, ps, cfg, peer_id_c, session_id_c, secret_c) { //XXX TODO this should create a new attempt and send the offer const session_id = MTY_StrToJS(session_id_c); const peer_id = MTY_StrToJS(peer_id_c); const secret = MTY_StrToJS(secret_c); if (ps) { const connect = () => { if (!PARSEC) { setTimeout(connect, 100); } else { PARSEC.clientConnect(session_id, peer_id, secret); PARSEC.setPeerID(PARSEC.getAttemptID(), peer_id); } }; connect(); } else { window.location.assign('parsec://peer_id=' + peer_id + '&host_secret=' + secret); } return 0; }, signal_init: function (s_out, role, host, port, loader_v, service_v, device_id, cbs, opaque) { const role_js = MTY_StrToJS(role); const host_js = MTY_StrToJS(host); // XXX TODO create context, but don't yet connect to websocket }, signal_destroy: function (s_out) { // XXX TODO full clean up and null out context }, signal_update: function (s, host, session_id) { const host_js = MTY_StrToJS(host); const session_id_js = MTY_StrToJS(session_id); // XXX TODO reconnect websocket with new session_id and websocket host return false; }, signal_stop: function (s) { // XXX TODO Disconnect from websocket, clear message queue }, // parsec SDK parsec_web_init: function () { if (PARSEC) return; AUDIO = document.createElement('audio'); document.body.appendChild(AUDIO); const container = document.createElement('div'); container.style.zIndex = -1; container.style.background = 'black'; container.style.position = 'fixed'; container.style.top = 0; container.style.right = 0; container.style.bottom = 0; container.style.left = 0; document.body.appendChild(container); const video = document.createElement('video'); video.muted = true; video.style.width = '100%'; video.style.height = '100%'; container.appendChild(video); PARSEC = new Parsec(video, AUDIO); }, parsec_web_destroy: function () { if (!PARSEC) return; PARSEC.destroy(); PARSEC = undefined; }, parsec_web_disconnect: function () { PARSEC.clientDisconnect(); }, parsec_web_get_status: function () { return DAEMON_WAITING ? PARSEC.Status.PARSEC_CONNECTING : PARSEC.clientGetStatus(); }, parsec_web_send_user_data: function (id, msg_c) { PARSEC.clientSendUserData(id, MTY_StrToJS(msg_c)); }, parsec_web_get_guests: function (jstr_c, len) { MTY_StrToC(JSON.stringify(PARSEC.clientGetGuests()), jstr_c, len); }, parsec_web_get_attempt_id: function (attempt_id_c, len) { MTY_StrToC(PARSEC.getAttemptID(), attempt_id_c, len); }, parsec_web_poll_events: function (event_str_c, len) { const event = PARSEC.clientPollEvents(); if (event) { MTY_StrToC(JSON.stringify(event), event_str_c, len); return true; } return false; }, parsec_web_get_buffer: function (key) { const buffer = PARSEC.getBuffer(key); if (buffer) { const ptr = MTY_Alloc(buffer.length); MTY_Memcpy(ptr, buffer); return ptr; } return 0; }, parsec_web_set_log_callback: function (callback_c, opaque) { PARSEC.setLogCallback((level, msg) => { const msg_c = MTY_Alloc(1024); MTY_StrToC(msg, msg_c, 1024); MTY_CFunc(callback_c)(level, msg_c, opaque); MTY_Free(msg_c); }); }, parsec_web_send_message: function (msg_c) { const msg = JSON.parse(MTY_StrToJS(msg_c)); PARSEC.clientSendMessage(msg); }, parsec_web_get_metrics: function (decode_ptr, encode_ptr, network_ptr) { const metrics = PARSEC.clientGetMetrics(); MTY_SetFloat(decode_ptr, metrics['decodeLatency']); MTY_SetFloat(encode_ptr, metrics['encodeLatency']); MTY_SetFloat(network_ptr, metrics['networkLatency']); }, parsec_web_get_network_failure: function () { return PARSEC.clientNetworkFailure(); }, parsec_web_get_self: function (owner_ptr, id_ptr) { const me = PARSEC.clientGetSelf(); MTY_SetInt8(owner_ptr, me['owner']); MTY_SetInt32(id_ptr, me['id']); }, parsec_web_get_host_mode: function () { return PARSEC.clientGetHostMode(); }, };