🚨 cleanup

This commit is contained in:
2024-07-15 22:09:03 +00:00
parent 41bdd55358
commit 9ed2f70701
8 changed files with 19 additions and 167 deletions

View File

@@ -1,7 +1,10 @@
version: "3.7" version: "3.7"
services: services:
gate: gate:
image: nginx:latest image: registry.gitlab.com/standa-fifik/battle-caster:latest
build:
context: .
dockerfile: Dockerfile
ports: ports:
- "8080:80" - "8080:80"
volumes: volumes:

View File

@@ -9,7 +9,9 @@ import { ChromecastReceiver } from './model/ChromecastListener';
const app = createApp(MapApp) const app = createApp(MapApp)
// @ts-ignore // @ts-ignore
app.provide(ReceiverSymbol, new MultiReceiver([ app.provide(ReceiverSymbol, new MultiReceiver([
// @ts-ignore
new BroadcastReceiver(), new BroadcastReceiver(),
// @ts-ignore
new ChromecastReceiver(), new ChromecastReceiver(),
])); ]));

View File

@@ -56,14 +56,13 @@ export class ChromecastSender implements Sender {
this.dataChannel.addEventListener('message', (event) => { this.dataChannel.addEventListener('message', (event) => {
console.log('data channel message', event.data); console.log('data channel message', event.data);
}); });
window['webrtcPeer'] = this.webrtcPeer;
window['dataChannel'] = this.dataChannel;
const offer = await this.webrtcPeer.createOffer(); const offer = await this.webrtcPeer.createOffer();
await this.webrtcPeer.setLocalDescription(offer); await this.webrtcPeer.setLocalDescription(offer);
// @ts-ignore // @ts-ignore
this.sendMessage({ type: 'RTC_OFFER', offer }); this.sendMessage({ type: 'RTC_OFFER', offer });
this.webrtcPeer.onicecandidate = (event: any) => { this.webrtcPeer.onicecandidate = (event: any) => {
if (event.candidate) { if (event.candidate) {
// @ts-ignore
this.sendMessage({ type: 'RTC_ICE', candidate: event.candidate }); this.sendMessage({ type: 'RTC_ICE', candidate: event.candidate });
// @ts-ignore // @ts-ignore
console.log('sending ice candidate', event.candidate); console.log('sending ice candidate', event.candidate);
@@ -159,7 +158,7 @@ export class ChromecastSender implements Sender {
export class ChromecastReceiver extends EventTarget implements Receiver { export class ChromecastReceiver extends EventTarget implements Receiver {
private webrtcPeer?: RTCPeerConnection private webrtcPeer?: RTCPeerConnection
private dataChannel: RTCDataChannel; private dataChannel?: RTCDataChannel;
constructor() { constructor() {
super(); super();
@@ -189,7 +188,7 @@ export class ChromecastReceiver extends EventTarget implements Receiver {
this.dispatchEvent(new CustomEvent(msg.type, {detail: msg})); this.dispatchEvent(new CustomEvent(msg.type, {detail: msg}));
this.dispatchEvent(new CustomEvent('all', {detail: msg})); this.dispatchEvent(new CustomEvent('all', {detail: msg}));
// log('data channel message', event.data); // log('data channel message', event.data);
this.dataChannel.send(JSON.stringify({ type: 'ACK', data: 'Hello, sender!' })); this.dataChannel?.send(JSON.stringify({ type: 'ACK', data: 'Hello, sender!' }));
} catch (err) { } catch (err) {
log('data channel error', err); log('data channel error', err);
} }
@@ -210,15 +209,16 @@ export class ChromecastReceiver extends EventTarget implements Receiver {
private initializeCastApi() { private initializeCastApi() {
try { try {
// @ts-ignore
const context = cast.framework.CastReceiverContext.getInstance(); const context = cast.framework.CastReceiverContext.getInstance();
// @ts-ignore
const options = new cast.framework.CastReceiverOptions(); const options = new cast.framework.CastReceiverOptions();
const playerManager = context.getPlayerManager();
context.addCustomMessageListener(CHANNEL, (event) => { context.addCustomMessageListener(CHANNEL, (event: any) => {
const msg = event.data; const msg = event.data;
log('msg', event.data.type); log('msg', event.data.type);
if (msg.type === 'RTC_OFFER') { if (msg.type === 'RTC_OFFER') {
this.initializeWebRTC(msg.offer, (data) => context.sendCustomMessage(CHANNEL, event.senderId, data)); this.initializeWebRTC(msg.offer, (data: any) => context.sendCustomMessage(CHANNEL, event.senderId, data));
} else if (msg.type === 'RTC_ICE') { } else if (msg.type === 'RTC_ICE') {
this.webrtcPeer?.addIceCandidate(msg.candidate); this.webrtcPeer?.addIceCandidate(msg.candidate);
} else { } else {
@@ -233,6 +233,7 @@ export class ChromecastReceiver extends EventTarget implements Receiver {
options.maxInactivity = 3600; // Development only options.maxInactivity = 3600; // Development only
context.start(options); context.start(options);
} catch (err) { } catch (err) {
// @ts-ignore
log('initializeCastApi error', err.stack); log('initializeCastApi error', err.stack);
} }
} }

View File

@@ -54,7 +54,7 @@ export class FileManager {
} }
} }
private extractMetaFromFileName(name: string): { width: number, height: number } { private extractMetaFromFileName(name: string): { width: number, height: number } | undefined {
const czepeku = new RegExp(/\[([0-9]+)x([0-9]+)\]/); const czepeku = new RegExp(/\[([0-9]+)x([0-9]+)\]/);
const czepekuMatches = name?.match(czepeku); const czepekuMatches = name?.match(czepeku);
if (czepekuMatches) { if (czepekuMatches) {

View File

@@ -1,13 +1,9 @@
import { InjectionKey } from "vue"; import { InjectionKey } from "vue";
import type { FileManager } from "./FileManager"; import type { FileManager } from "./FileManager";
import type { CastSender } from "./CastSender.ts_";
import type { CastReceiver } from "./CastReceiver.ts_";
import { Receiver, Sender } from "./CommunicationChannel"; import { Receiver, Sender } from "./CommunicationChannel";
export const FileManagerSymbol = Symbol("FileManager") as InjectionKey<FileManager>; export const FileManagerSymbol = Symbol("FileManager") as InjectionKey<FileManager>;
export const CastSenderSymbol = Symbol("CastSender") as InjectionKey<CastSender>;
export const CastReceiverSymbol = Symbol("CastReceiver") as InjectionKey<CastReceiver>;
export const CastTypeSymbol = Symbol("CastType") as InjectionKey<"sender" | "receiver">; export const CastTypeSymbol = Symbol("CastType") as InjectionKey<"sender" | "receiver">;
export const SenderSymbol = Symbol('Sender') as InjectionKey<Sender>; export const SenderSymbol = Symbol('Sender') as InjectionKey<Sender>;
export const ReceiverSymbol = Symbol('Receiver') as InjectionKey<Receiver>; export const ReceiverSymbol = Symbol('Receiver') as InjectionKey<Receiver>;

View File

@@ -14,7 +14,6 @@
<input type="number" v-model="imageWidth" /> <input type="number" v-model="imageWidth" />
<label>Screen Diameter</label> <label>Screen Diameter</label>
<input type="number" v-model="screenDiameterInch" /> <input type="number" v-model="screenDiameterInch" />
<div>DPI: {{ screenDPI }}</div>
<label>Flip <input type="checkbox" v-model="flipped"></label> <label>Flip <input type="checkbox" v-model="flipped"></label>
<label>Position (X/Y)</label> <label>Position (X/Y)</label>
<input type="range" min="0" max="100" v-model="positionX" /> <input type="range" min="0" max="100" v-model="positionX" />
@@ -54,7 +53,7 @@ watch(() => screenDiameterInch.value, (value) => {
}) })
}); });
watch(() => [positionX.value, positionY.value, flipped.value], (value) => { watch(() => [positionX.value, positionY.value, flipped.value], () => {
sender?.sendMessage({ sender?.sendMessage({
type: 'changePosition', type: 'changePosition',
x: positionX.value, x: positionX.value,
@@ -79,6 +78,9 @@ function openMapWindow() {
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
function onStreamImage() { function onStreamImage() {
if (!openedFile.value?.path) {
return;
}
const image = new Image() const image = new Image()
image.onload = async () => { image.onload = async () => {
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');

View File

@@ -1,132 +0,0 @@
<template>
<div>
<fieldset>
<legend>Image settings</legend>
<label>Width</label>
<input type="number" v-model="imageWidth" />
<label>Screen Diameter</label>
<input type="number" v-model="screenDiameterInch" />
<div>DPI: {{ screenDPI }}</div>
<div style="max-width: 32px; height: 32px; overflow: hidden;">
<google-cast-launcher style="max-width: 2rem" ></google-cast-launcher>
</div>
</fieldset>
<FileManager @openFile="openFile" />
</div>
</template>
<script setup lang="ts">
import FileManager from '../../components/FileManager/FileManager.vue';
import type { FileWithMeta } from '../../model/FileManager';
import {ref, computed, inject, watch} from 'vue';
import {CastTypeSymbol, CastReceiverSymbol, CastSenderSymbol} from '../../model/injectionSymbols';
const openedFile = ref<FileWithMeta>()
const castType = inject(CastTypeSymbol);
const receiver = inject(CastReceiverSymbol);
const sender = inject(CastSenderSymbol);
const canvas = ref<HTMLCanvasElement>();
const imageWidth = ref(20);
const screenDiameterInch = ref(65);
const screenDPI = computed(() => {
const diaPx = Math.sqrt(window.screen.width**2 + window.screen.height ** 2);
return diaPx / screenDiameterInch.value;
})
watch(() => imageWidth.value, (value) => {
if (sender) {
sender.sendMessage({
type: 'imageWidth',
imageWidth: value
})
}
});
function openFile(file: FileWithMeta) {
console.log('open file', file)
openedFile.value = file
imageWidth.value = file.width ?? 20;
if (sender) {
sender.sendMessage({
type: 'loadMap',
file
})
const img = new Image();
img.onload = () => {
canvas.value!.width = img.naturalWidth;
canvas.value!.height = img.naturalHeight;
const ctx = canvas.value!.getContext('2d')!;
ctx.drawImage(img, 0, 0);
const msgs = [];
const chunkWidth = 32;
const chunkHeight = 32;
for (let x = 0; x< 1920; x += chunkWidth) {
for (let y = 0; y < 1080; y += chunkHeight) {
const data = ctx.getImageData(x, y, chunkWidth, chunkHeight);
const msg = {
type: 'imageData',
imageData: {
data: [...data.data],
width: data.width,
height: data.height,
x,
y,
},
};
msgs.push(msg);
sender.sendMessage(msg);
}
}
ctx.clearRect(0, 0, img.naturalWidth, img.naturalHeight);
for (const msg of msgs) {
loadImageData(msg);
}
};
img.src = file.path;
}
}
function loadImageData(detail) {
const imageData = new ImageData(
new Uint8ClampedArray(detail.imageData.data),
detail.imageData.width,
detail.imageData.height
)
const ctx = canvas.value!.getContext('2d')!;
ctx.putImageData(imageData, detail.imageData.x, detail.imageData.y);
}
if (receiver) {
receiver.addEventListener('message', ({detail}) => {
if (detail.type === 'loadMap') {
openFile(detail.file);
}
if (detail.type === 'imageWidth') {
imageWidth.value = detail.imageWidth;
}
if (detail.type === 'imageData') {
loadImageData(detail);
}
});
}
</script>
<style>
.aside {
position: fixed;
overflow: auto;
width: 300px;
height: 100vh;
overflow: auto;
right:0;
background: rgba(0,0,0,0.8);
border-left: #555 2px solid;
backdrop-filter: blur(5px);
}
</style>

View File

@@ -22,7 +22,6 @@ import { computed, defineProps, inject, ref, watch } from 'vue';
import {ReceiverSymbol} from '../../model/injectionSymbols'; import {ReceiverSymbol} from '../../model/injectionSymbols';
const video = ref<HTMLVideoElement>(); const video = ref<HTMLVideoElement>();
const image = ref<HTMLImageElement>();
const canvas = ref<HTMLCanvasElement>(); const canvas = ref<HTMLCanvasElement>();
const props = defineProps<{ const props = defineProps<{
@@ -37,12 +36,7 @@ const isImage = computed(() => props.src?.endsWith('.png') || props.src?.endsWit
const isVideo = computed(() => props.src?.endsWith('.mp4') || props.src?.endsWith('.webm')); const isVideo = computed(() => props.src?.endsWith('.mp4') || props.src?.endsWith('.webm'));
const mediaDimensions = ref({width: 0, height: 0}); const mediaDimensions = ref({width: 0, height: 0});
const virtualMediaDimensions = ref({width: 0, height: 0});
const windowSize = {
width: window.innerWidth,
height: window.innerHeight,
};
watch(() => props.src, (src) => { watch(() => props.src, (src) => {
if (isImage.value) { if (isImage.value) {
@@ -113,14 +107,6 @@ const dynamicStyle = computed(() => {
}); });
function onImageLoaded(event: Event) {
console.log('image loaded', event.target);
mediaDimensions.value = {
width: image.value!.naturalWidth,
height: image.value!.naturalHeight,
};
}
function onVideoLoaded(event: Event) { function onVideoLoaded(event: Event) {
console.log('video loaded', event.target); console.log('video loaded', event.target);
mediaDimensions.value = { mediaDimensions.value = {
@@ -129,12 +115,6 @@ function onVideoLoaded(event: Event) {
}; };
} }
function updateImageSize() {
if (image.value) {
image.value.width = props.width;
}
}
</script> </script>
<style> <style>
.map-scene { .map-scene {