update states.

This commit is contained in:
Miroslav Šedivý 2020-11-08 21:19:46 +01:00
parent a98866e5cb
commit d6c3c4b2aa
4 changed files with 215 additions and 95 deletions

View File

@ -1,48 +1,146 @@
<template> <template>
<div> <div>
<button @click="connect()">Connect</button> <div style="float: right; max-width: 500px">
<button @click="disconnect()">Disonnect</button> <h3>State</h3>
<table class="states" v-if="loaded">
<template v-if="loaded && neko.connected"> <tr class="ok">
<button v-if="!is_controlling" @click="neko.control.request()">request control</button> <th>connection.websocket</th>
<button v-else @click="neko.control.release()">release control</button> <td>{{ neko.state.connection.websocket }}</td>
</tr>
<button @click="neko.video.pause()">pause stream</button> <tr class="ok">
<button @click="neko.video.play()">play stream</button><br /> <th>connection.webrtc</th>
</template> <td>{{ neko.state.connection.webrtc }}</td>
</tr>
<table class="states" v-if="loaded"> <tr>
<tr> <th>connection.type</th>
<th>is connected</th> <td>{{ neko.state.connection.type }}</td>
<td>{{ neko.connected ? 'yes' : 'no' }}</td> </tr>
</tr> <tr>
<tr> <th>connection.can_watch</th>
<th>is contolling</th> <td>{{ neko.state.connection.can_watch }}</td>
<td>{{ is_controlling ? 'yes' : 'no' }}</td> </tr>
</tr> <tr>
<tr> <th>connection.can_control</th>
<th>websocket state</th> <td>{{ neko.state.connection.can_control }}</td>
<td>{{ neko.state.connection.websocket }}</td> </tr>
</tr> <tr>
<tr> <th>connection.clipboard_access</th>
<th>webrtc state</th> <td>{{ neko.state.connection.clipboard_access }}</td>
<td>{{ neko.state.connection.webrtc }}</td> </tr>
</tr> <tr class="ok">
</table> <th>video.playable</th>
<td>{{ neko.state.video.playable }}</td>
<div ref="container" style="width: 1280px; height: 720px; border: 2px solid red"> </tr>
<neko-canvas ref="neko" /> <tr class="ok">
<th>video.playing</th>
<td>{{ neko.state.video.playing }}</td>
</tr>
<tr>
<th>video.volume</th>
<td>{{ neko.state.video.volume }}</td>
</tr>
<tr class="ok">
<th>control.scroll.inverse</th>
<td><input type="checkbox" v-model="neko.state.control.scroll.inverse" /></td>
</tr>
<tr class="ok">
<th>control.scroll.sensitivity</th>
<td><input type="number" v-model="neko.state.control.scroll.sensitivity" /></td>
</tr>
<tr>
<th>control.host</th>
<td>{{ neko.state.control.host }}</td>
</tr>
<tr class="ok">
<th>screen.size.width</th>
<td>{{ neko.state.screen.size.width }}</td>
</tr>
<tr class="ok">
<th>screen.size.height</th>
<td>{{ neko.state.screen.size.height }}</td>
</tr>
<tr class="ok">
<th>screen.size.rate</th>
<td>{{ neko.state.screen.size.rate }}</td>
</tr>
<tr class="ok">
<th>screen.configurations</th>
<td>
<select
:value="Object.values(neko.state.screen.size).join()"
@input="
a = String($event.target.value).split(',')
neko.screen.size(parseInt(a[0]), parseInt(a[1]), parseInt(a[2]))
"
>
<option
v-for="{ width, height, rate } in neko.state.screen.configurations"
:key="width + height + rate"
:value="[width, height, rate].join()"
>
{{ width }}x{{ height }}@{{ rate }}
</option>
</select>
</td>
</tr>
<tr>
<th>screen.is_fullscreen</th>
<td>{{ neko.state.screen.is_fullscreen }}</td>
</tr>
<tr class="ok">
<th>member.id</th>
<td>{{ neko.state.member.id }}</td>
</tr>
<tr class="ok">
<th>member.name</th>
<td>{{ neko.state.member.name }}</td>
</tr>
<tr>
<th>member.is_admin</th>
<td>{{ neko.state.member.is_admin }}</td>
</tr>
<tr>
<th>member.is_watching</th>
<td>{{ neko.state.member.is_watching }}</td>
</tr>
<tr class="ok">
<th>member.is_controlling</th>
<td>{{ neko.state.member.is_controlling }}</td>
</tr>
<tr>
<th>member.can_watch</th>
<td>{{ neko.state.member.can_watch }}</td>
</tr>
<tr>
<th>member.can_control</th>
<td>{{ neko.state.member.can_control }}</td>
</tr>
<tr>
<th>member.clipboard_access</th>
<td>{{ neko.state.member.clipboard_access }}</td>
</tr>
<tr>
<th>members</th>
<td>{{ neko.state.members }}</td>
</tr>
</table>
</div> </div>
<div>
<button @click="connect()">Connect</button>
<button @click="disconnect()">Disonnect</button>
<template v-if="loaded"> <template v-if="loaded && neko.connected">
<button <button v-if="!is_controlling" @click="neko.control.request()">request control</button>
v-for="{ width, height, rate } in available_screen_sizes" <button v-else @click="neko.control.release()">release control</button>
:key="width + height + rate"
@click="neko.screen.size(width, height, rate)" <button @click="neko.video.pause()">pause stream</button>
> <button @click="neko.video.play()">play stream</button><br />
{{ width }}x{{ height }}@{{ rate }} </template>
</button>
</template> <div ref="container" style="width: 1280px; height: 720px; border: 2px solid red">
<neko-canvas ref="neko" />
</div>
</div>
</div> </div>
</template> </template>
@ -55,7 +153,11 @@
} }
th { th {
text-align: right; text-align: left;
}
.ok {
background: #97f197;
} }
} }
</style> </style>
@ -80,10 +182,6 @@
return this.neko.state.member.is_controlling return this.neko.state.member.is_controlling
} }
get available_screen_sizes() {
return this.neko.state.screen.configurations
}
connect() { connect() {
this.neko.connect('ws://192.168.1.20:3000/', 'admin', 'test') this.neko.connect('ws://192.168.1.20:3000/', 'admin', 'test')
} }
@ -128,11 +226,8 @@
this.neko.events.on('clipboard.update', (text) => { this.neko.events.on('clipboard.update', (text) => {
console.log('clipboard.update', text) console.log('clipboard.update', text)
}) })
this.neko.events.on('screen.configuration', (configurations) => { this.neko.events.on('screen.size', (id) => {
console.log('screen.configuration', configurations) console.log('screen.size', id)
})
this.neko.events.on('screen.size', (width, height, rate) => {
console.log('screen.size', width, height, rate)
}) })
this.neko.events.on('broadcast.status', (payload) => { this.neko.events.on('broadcast.status', (payload) => {
console.log('broadcast.status', payload) console.log('broadcast.status', payload)

View File

@ -12,7 +12,7 @@
:screenHeight="state.screen.size.height" :screenHeight="state.screen.size.height"
:isControling="state.member.is_controlling" :isControling="state.member.is_controlling"
:scrollSensitivity="state.control.scroll.sensitivity" :scrollSensitivity="state.control.scroll.sensitivity"
:scrollInvert="state.control.scroll.invert" :scrollInvert="state.control.scroll.inverse"
/> />
</div> </div>
</div> </div>
@ -51,6 +51,7 @@
import { NekoWebSocket } from '~/internal/websocket' import { NekoWebSocket } from '~/internal/websocket'
import { NekoWebRTC } from '~/internal/webrtc' import { NekoWebRTC } from '~/internal/webrtc'
import { NekoMessages } from '~/internal/messages' import { NekoMessages } from '~/internal/messages'
import { register as VideoRegister } from '~/internal/video'
import NekoState from '~/types/state' import NekoState from '~/types/state'
import Overlay from './overlay.vue' import Overlay from './overlay.vue'
@ -93,7 +94,7 @@
control: { control: {
scroll: { scroll: {
inverse: true, inverse: true,
sensitivity: 10, sensitivity: 1,
}, },
host: null, host: null,
}, },
@ -125,6 +126,11 @@
return this.state.connection.websocket == 'connected' && this.state.connection.webrtc == 'connected' return this.state.connection.websocket == 'connected' && this.state.connection.webrtc == 'connected'
} }
@Watch('state.screen.size')
onScreenSizeChanged() {
this.onResize()
}
public control = { public control = {
request: () => { request: () => {
this.websocket.send('control/request') this.websocket.send('control/request')
@ -174,6 +180,9 @@
Vue.set(this.state.member, 'is_controlling', id != null && id === this.state.member.id) Vue.set(this.state.member, 'is_controlling', id != null && id === this.state.member.id)
}) })
// Video
VideoRegister(this.video, this.state.video)
// WebSocket // WebSocket
this.websocket.on('message', async (event: string, payload: any) => { this.websocket.on('message', async (event: string, payload: any) => {
switch (event) { switch (event) {
@ -185,40 +194,6 @@
this.websocket.send('signal/answer', { sdp, displayname: this.state.member.name }) this.websocket.send('signal/answer', { sdp, displayname: this.state.member.name })
} catch (e) {} } catch (e) {}
break break
case 'screen/resolution':
Vue.set(this.state.screen, 'size', payload)
this.onResize()
break
case 'screen/configurations':
let data = []
for (const i of Object.keys(payload.configurations)) {
const { width, height, rates } = payload.configurations[i]
if (width >= 600 && height >= 300) {
for (const j of Object.keys(rates)) {
const rate = rates[j]
if (rate === 30 || rate === 60) {
data.push({
width,
height,
rate,
})
}
}
}
}
let conf = data.sort((a, b) => {
if (b.width === a.width && b.height == a.height) {
return b.rate - a.rate
} else if (b.width === a.width) {
return b.height - a.height
}
return b.width - a.width
})
Vue.set(this.state.screen, 'configurations', conf)
this.onResize()
break
} }
}) })
this.websocket.on('connecting', () => { this.websocket.on('connecting', () => {
@ -261,6 +236,8 @@
this.webrtc.on('disconnected', () => { this.webrtc.on('disconnected', () => {
Vue.set(this.state.connection, 'webrtc', 'disconnected') Vue.set(this.state.connection, 'webrtc', 'disconnected')
this.events.emit('system.webrtc', 'disconnected') this.events.emit('system.webrtc', 'disconnected')
// @ts-ignore
this.video.src = null
}) })
} }

View File

@ -1,3 +1,4 @@
import Vue from 'vue'
import { Member, ScreenConfigurations } from '../types/structs' import { Member, ScreenConfigurations } from '../types/structs'
import { EVENT } from '../types/events' import { EVENT } from '../types/events'
import { import {
@ -31,8 +32,7 @@ export interface NekoEvents {
['control.request']: (id: string) => void ['control.request']: (id: string) => void
['control.requesting']: (id: string) => void ['control.requesting']: (id: string) => void
['clipboard.update']: (text: string) => void ['clipboard.update']: (text: string) => void
['screen.configuration']: (configurations: ScreenConfigurations) => void ['screen.size']: (id: string) => void
['screen.size']: (width: number, height: number, rate: number) => void
['broadcast.status']: (url: string, isActive: boolean) => void ['broadcast.status']: (url: string, isActive: boolean) => void
['member.ban']: (id: string, target: string) => void ['member.ban']: (id: string, target: string) => void
['member.kick']: (id: string, target: string) => void ['member.kick']: (id: string, target: string) => void
@ -132,15 +132,38 @@ export class NekoMessages extends EventEmitter<NekoEvents> {
// Screen Events // Screen Events
///////////////////////////// /////////////////////////////
protected [EVENT.SCREEN.CONFIGURATIONS]({ configurations }: ScreenConfigurationsPayload) { protected [EVENT.SCREEN.CONFIGURATIONS]({ configurations }: ScreenConfigurationsPayload) {
console.log('EVENT.SCREEN.CONFIGURATIONS') let data = []
this.emit('screen.configuration', configurations) for (const i of Object.keys(configurations)) {
//video.setConfigurations(configurations) const { width, height, rates } = configurations[i]
if (width >= 600 && height >= 300) {
for (const j of Object.keys(rates)) {
const rate = rates[j]
if (rate === 30 || rate === 60) {
data.push({
width,
height,
rate,
})
}
}
}
}
let conf = data.sort((a, b) => {
if (b.width === a.width && b.height == a.height) {
return b.rate - a.rate
} else if (b.width === a.width) {
return b.height - a.height
}
return b.width - a.width
})
Vue.set(this.state.screen, 'configurations', conf)
} }
protected [EVENT.SCREEN.RESOLUTION]({ id, width, height, rate }: ScreenResolutionPayload) { protected [EVENT.SCREEN.RESOLUTION]({ id, width, height, rate }: ScreenResolutionPayload) {
console.log('EVENT.SCREEN.RESOLUTION') Vue.set(this.state.screen, 'size', { width, height, rate })
this.emit('screen.size', width, height, rate) if (id) this.emit('screen.size', id)
//video.setResolution({ width, height, rate })
} }
///////////////////////////// /////////////////////////////

25
src/internal/video.ts Normal file
View File

@ -0,0 +1,25 @@
import Vue from 'vue'
import { Video } from '~/types/state'
export function register(el: HTMLVideoElement, state: Video) {
el.addEventListener('canplaythrough', () => {
Vue.set(state, 'playable', true)
})
el.addEventListener('playing', () => {
Vue.set(state, 'playing', true)
})
el.addEventListener('pause', () => {
Vue.set(state, 'playing', false)
})
el.addEventListener('emptied', () => {
Vue.set(state, 'playable', false)
Vue.set(state, 'playing', false)
})
el.addEventListener('error', () => {
Vue.set(state, 'playable', false)
Vue.set(state, 'playing', false)
})
el.addEventListener('volumechange', (value) => {
Vue.set(state, 'volume', value)
})
}