diff --git a/RemoteCamera/build/debug/README.md b/RemoteCamera/build/debug/README.md index baa0ace..978b415 100644 --- a/RemoteCamera/build/debug/README.md +++ b/RemoteCamera/build/debug/README.md @@ -1,9 +1,11 @@ # RemoteCamera -Connect to a V4L2 camera on server via Antunnel. +Connect to a V4L2 camera on server via Antunnel plugin. + +![](https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteCamera/screenshot.jpg) This application reauires the **tunel plugin** and the **ant-tunnel v4l2 publisher** on the server-side ## Change log -* v0.1.2-a: user worker for jpeg decoding \ No newline at end of file +* v0.1.2-a: user worker for jpeg decoding diff --git a/RemoteCamera/build/debug/decoder.js b/RemoteCamera/build/debug/decoder.js index 636d169..2caf1c4 100644 --- a/RemoteCamera/build/debug/decoder.js +++ b/RemoteCamera/build/debug/decoder.js @@ -31,12 +31,14 @@ decode = (arr) => } onmessage = (e) => { - if(e.data.libjpeg) - { - importScripts(e.data.libjpeg); - } - else - { - decode(e.data); + switch (e.data.cmd) { + case 0x0: + importScripts(e.data.data); + break; + case 0x1: + decode(e.data.data); + break; + default: + console.error("Unknown command " + e.data.cmd); } } \ No newline at end of file diff --git a/RemoteCamera/build/debug/main.js b/RemoteCamera/build/debug/main.js index add8b52..0f0e292 100644 --- a/RemoteCamera/build/debug/main.js +++ b/RemoteCamera/build/debug/main.js @@ -1 +1 @@ -(function(){var t;(t=class extends this.OS.application.BaseApplication{constructor(t){super("RemoteCamera",t)}main(){var t,e,s;for(this.decoder=new Worker("pkg://RemoteCamera/decoder.js".asFileHandle().getlink()),this.decoder.onmessage=t=>this.paint(t.data),this.decoder.postMessage({libjpeg:"pkg://libjpeg/jpg.js".asFileHandle().getlink()}),this.mute=!1,this.player=this.find("player"),this.qctl=this.find("qctl"),this.fpsctl=this.find("fpsctl"),this.cam_setting={w:640,h:480,fps:10,quality:60},t=[],e=s=5;s<=30;e=s+=5)t.push({text:""+e,value:e});return this.fpsctl.data=t,this.fpsctl.selected=this.cam_setting.fps/5-1,this.fpsctl.onlistselect=t=>{if(!this.mute)return this.cam_setting.fps=t.data.item.data.value,this.setCameraSetting()},this.qctl.value=this.cam_setting.quality,this.resoctl=this.find("resoctl"),this.resoctl.data=[{text:__("320x240"),mode:"qvga"},{text:__("640x480"),selected:!0,mode:"vga"},{text:__("800x600"),mode:"svga"},{text:__("1024x760"),mode:"hd"},{text:__("1920×1080"),mode:"fhd"}],this.resoctl.onlistselect=t=>{if(!this.mute){switch(t.data.item.data.mode){case"qvga":this.cam_setting.w=320,this.cam_setting.h=240;break;case"vga":this.cam_setting.w=640,this.cam_setting.h=480;break;case"svga":this.cam_setting.w=800,this.cam_setting.h=600;break;case"hd":this.cam_setting.w=1024,this.cam_setting.h=768;break;case"fhd":this.cam_setting.w=1920,this.cam_setting.h=1080}return this.setCameraSetting()}},this.qctl.onvaluechange=t=>{if(!this.mute)return this.cam_setting.quality=t.data,this.setCameraSetting()},Antunnel.tunnel?this.setting.channel?this.openSession():this.requestChannel():this.notify(__("Antunnel service is not available"))}requestChannel(){return this.openDialog("PromptDialog",{title:__("Enter camera channel"),label:__("Please enter camera channel name")}).then(t=>(this.setting.channel=t,this.sub?(this.sub.onclose=t=>this.openSession(),this.sub.close()):this.openSession()))}paint(t){var e,s,i;return s=new Uint8Array(t.pixels),e=this.player.getContext("2d",{alpha:!1}),this.player.width=t.w,this.player.height=t.h,(i=e.createImageData(t.w,t.h)).data.set(s),e.putImageData(i,0,0)}menu(){return{text:"__(Option)",nodes:[{text:"__(Camera channel)"}],onchildselect:t=>this.requestChannel()}}openSession(){if(Antunnel&&this.setting.channel)return this.tunnel=Antunnel.tunnel,this.sub=new Antunnel.Subscriber(this.setting.channel),this.sub.onopen=()=>console.log("Subscribed to camera channel"),this.sub.onerror=t=>this.error(__("Error: {0}",new TextDecoder("utf-8").decode(t.data)),t),this.sub.onctrl=t=>{switch(this.cam_setting.w=Antunnel.Msg.int_from(t.data,0),this.cam_setting.h=Antunnel.Msg.int_from(t.data,2),this.cam_setting.fps=t.data[4],this.cam_setting.quality=t.data[5],this.mute=!0,this.qctl.value=this.cam_setting.quality,`${this.cam_setting.w}x${this.cam_setting.h}`){case"320x240":this.resoctl.selected=0;break;case"640x480":this.resoctl.selected=1;break;case"800x600":this.resoctl.selected=2;break;case"1024x768":this.resoctl.selected=3;break;case"1920x1080":this.resoctl.selected=4}return this.fpsctl.selected=this.cam_setting.fps/5-1,this.mute=!1},this.sub.onmessage=t=>{if(this.decoder)return this.decoder.postMessage(t.data.buffer,[t.data.buffer])},this.sub.onclose=()=>(this.sub=void 0,this.notify(__("Unsubscribed to the camera service")),this.quit()),Antunnel.tunnel.subscribe(this.sub)}cleanup(){if(this.sub&&this.sub.close(),this.decoder)return this.decoder.terminate()}setCameraSetting(){var t;if(this.sub)return(t=new Uint8Array(6)).set(Antunnel.Msg.bytes_of(this.cam_setting.w),0),t.set(Antunnel.Msg.bytes_of(this.cam_setting.h),2),t[4]=this.cam_setting.fps,t[5]=this.cam_setting.quality,this.sub.send(Antunnel.Msg.CTRL,t)}}).singleton=!0,this.OS.register("RemoteCamera",t)}).call(this); \ No newline at end of file +(function(){var t;(t=class extends this.OS.application.BaseApplication{constructor(t){super("RemoteCamera",t)}main(){var t,e,s;for(this.decoder=new Worker("pkg://RemoteCamera/decoder.js".asFileHandle().getlink()),this.decoder.onmessage=t=>this.paint(t.data),this.decoder.postMessage({cmd:0,data:"pkg://libjpeg/jpg.js".asFileHandle().getlink()}),this.mute=!1,this.player=this.find("player"),this.qctl=this.find("qctl"),this.fpsctl=this.find("fpsctl"),this.cam_setting={w:640,h:480,fps:10,quality:60},t=[],e=s=5;s<=30;e=s+=5)t.push({text:""+e,value:e});return this.fpsctl.data=t,this.fpsctl.selected=this.cam_setting.fps/5-1,this.fpsctl.onlistselect=t=>{if(!this.mute)return this.cam_setting.fps=t.data.item.data.value,this.setCameraSetting()},this.qctl.value=this.cam_setting.quality,this.resoctl=this.find("resoctl"),this.resoctl.data=[{text:__("320x240"),mode:"qvga"},{text:__("640x480"),selected:!0,mode:"vga"},{text:__("800x600"),mode:"svga"},{text:__("1024x760"),mode:"hd"},{text:__("1920×1080"),mode:"fhd"}],this.resoctl.onlistselect=t=>{if(!this.mute){switch(t.data.item.data.mode){case"qvga":this.cam_setting.w=320,this.cam_setting.h=240;break;case"vga":this.cam_setting.w=640,this.cam_setting.h=480;break;case"svga":this.cam_setting.w=800,this.cam_setting.h=600;break;case"hd":this.cam_setting.w=1024,this.cam_setting.h=768;break;case"fhd":this.cam_setting.w=1920,this.cam_setting.h=1080}return this.setCameraSetting()}},this.qctl.onvaluechange=t=>{if(!this.mute)return this.cam_setting.quality=t.data,this.setCameraSetting()},Antunnel.tunnel?this.setting.channel?this.openSession():this.requestChannel():this.notify(__("Antunnel service is not available"))}requestChannel(){return this.openDialog("PromptDialog",{title:__("Enter camera channel"),label:__("Please enter camera channel name")}).then(t=>(this.setting.channel=t,this.sub?(this.sub.onclose=t=>this.openSession(),this.sub.close()):this.openSession()))}paint(t){var e,s,i;return s=new Uint8Array(t.pixels),e=this.player.getContext("2d",{alpha:!1}),this.player.width=t.w,this.player.height=t.h,(i=e.createImageData(t.w,t.h)).data.set(s),e.putImageData(i,0,0)}menu(){return{text:"__(Option)",nodes:[{text:"__(Camera channel)"}],onchildselect:t=>this.requestChannel()}}openSession(){if(Antunnel&&this.setting.channel)return this.tunnel=Antunnel.tunnel,this.sub=new Antunnel.Subscriber(this.setting.channel),this.sub.onopen=()=>console.log("Subscribed to camera channel"),this.sub.onerror=t=>this.error(__("Error: {0}",new TextDecoder("utf-8").decode(t.data)),t),this.sub.onctrl=t=>{switch(this.cam_setting.w=Antunnel.Msg.int_from(t.data,0),this.cam_setting.h=Antunnel.Msg.int_from(t.data,2),this.cam_setting.fps=t.data[4],this.cam_setting.quality=t.data[5],this.mute=!0,this.qctl.value=this.cam_setting.quality,`${this.cam_setting.w}x${this.cam_setting.h}`){case"320x240":this.resoctl.selected=0;break;case"640x480":this.resoctl.selected=1;break;case"800x600":this.resoctl.selected=2;break;case"1024x768":this.resoctl.selected=3;break;case"1920x1080":this.resoctl.selected=4}return this.fpsctl.selected=this.cam_setting.fps/5-1,this.mute=!1},this.sub.onmessage=t=>{var e;if(this.decoder)return e={cmd:1,data:t.data.buffer},this.decoder.postMessage(e,[e.data])},this.sub.onclose=()=>(this.sub=void 0,this.notify(__("Unsubscribed to the camera service")),this.quit()),Antunnel.tunnel.subscribe(this.sub)}cleanup(){if(this.sub&&this.sub.close(),this.decoder)return this.decoder.terminate()}setCameraSetting(){var t;if(this.sub)return(t=new Uint8Array(6)).set(Antunnel.Msg.bytes_of(this.cam_setting.w),0),t.set(Antunnel.Msg.bytes_of(this.cam_setting.h),2),t[4]=this.cam_setting.fps,t[5]=this.cam_setting.quality,this.sub.send(Antunnel.Msg.CTRL,t)}}).singleton=!0,this.OS.register("RemoteCamera",t)}).call(this); \ No newline at end of file diff --git a/RemoteCamera/build/debug/package.json b/RemoteCamera/build/debug/package.json index ccefe36..65cf923 100644 --- a/RemoteCamera/build/debug/package.json +++ b/RemoteCamera/build/debug/package.json @@ -7,7 +7,7 @@ "author": "", "email": "" }, - "version":"0.1.2-a", + "version":"0.1.3-a", "category":"Other", "iconclass":"fa fa-camera", "mimes":["none"], diff --git a/RemoteCamera/build/release/RemoteCamera.zip b/RemoteCamera/build/release/RemoteCamera.zip index 04577a6..7d8ac10 100644 Binary files a/RemoteCamera/build/release/RemoteCamera.zip and b/RemoteCamera/build/release/RemoteCamera.zip differ diff --git a/RemoteCamera/coffees/main.coffee b/RemoteCamera/coffees/main.coffee index 0f99cc6..3c13d60 100644 --- a/RemoteCamera/coffees/main.coffee +++ b/RemoteCamera/coffees/main.coffee @@ -9,7 +9,7 @@ class RemoteCamera extends this.OS.application.BaseApplication @decoder.onmessage = (e) => @paint e.data - @decoder.postMessage {libjpeg: "pkg://libjpeg/jpg.js".asFileHandle().getlink()} + @decoder.postMessage {cmd:0x0 ,data: "pkg://libjpeg/jpg.js".asFileHandle().getlink()} @mute = false @player = @find "player" @@ -166,7 +166,11 @@ class RemoteCamera extends this.OS.application.BaseApplication @sub.onmessage = (e) => return unless @decoder - @decoder.postMessage e.data.buffer, [e.data.buffer] + msg = { + cmd: 0x1, + data: e.data.buffer + } + @decoder.postMessage msg, [msg.data] @sub.onclose = () => @sub = undefined diff --git a/RemoteCamera/js/decoder.js b/RemoteCamera/js/decoder.js index 636d169..2caf1c4 100644 --- a/RemoteCamera/js/decoder.js +++ b/RemoteCamera/js/decoder.js @@ -31,12 +31,14 @@ decode = (arr) => } onmessage = (e) => { - if(e.data.libjpeg) - { - importScripts(e.data.libjpeg); - } - else - { - decode(e.data); + switch (e.data.cmd) { + case 0x0: + importScripts(e.data.data); + break; + case 0x1: + decode(e.data.data); + break; + default: + console.error("Unknown command " + e.data.cmd); } } \ No newline at end of file diff --git a/RemoteCamera/package.json b/RemoteCamera/package.json index ccefe36..65cf923 100644 --- a/RemoteCamera/package.json +++ b/RemoteCamera/package.json @@ -7,7 +7,7 @@ "author": "", "email": "" }, - "version":"0.1.2-a", + "version":"0.1.3-a", "category":"Other", "iconclass":"fa fa-camera", "mimes":["none"], diff --git a/packages.json b/packages.json index 40a222a..6f8d966 100644 --- a/packages.json +++ b/packages.json @@ -205,7 +205,7 @@ "description": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteCamera/README.md", "category": "Other", "author": "", - "version": "0.1.2-a", + "version": "0.1.3-a", "dependencies": ["libjpeg@0.1.1-a","Antunnel@0.1.8-a"], "download": "https://raw.githubusercontent.com/lxsang/antosdk-apps/master/RemoteCamera/build/release/RemoteCamera.zip" },