const CMD='/data/adb/modules/virtualcam/control.sh'; function log(m,t){const e=document.getElementById('console');const d=new Date(); e.innerHTML+=`
[${d.toLocaleTimeString()}] ${m}
`;e.scrollTop=e.scrollHeight} async function exec(c){try{return await KSU.exec(c)}catch(e){log('exec error','err');return null}} async function status(){ const r=await exec(CMD+' status');if(!r)return; try{ const s=JSON.parse(r);const d=document.getElementById('status-dash'); const items=[['Provider',s.provider_pid>0?'green':'red',s.provider_pid>0?'Running':'Stopped'], ['Feeder',s.feeder_pid>0?'green':'red',s.feeder_pid>0?'Running':'Stopped'], ['Service',s.service_registered==1?'green':'red',s.service_registered==1?'Registered':'Not found'], ['v4l2',s.v4l2_loaded==1?'green':'red',s.v4l2_loaded==1?'Loaded':'Missing'], ['Device','yellow',s.video0||'N/A']]; d.innerHTML=items.map(i=>`
${i[0]}${i[2]}
`).join(''); log('Status updated','ok'); }catch(e){log('Parse error','err')} } document.addEventListener('DOMContentLoaded',()=>{ status(); document.querySelectorAll('.src-btn').forEach(b=>{ b.addEventListener('click',()=>{ document.querySelectorAll('.src-btn').forEach(x=>x.classList.remove('active')); b.classList.add('active'); document.getElementById('rtsp-config').classList.toggle('hidden',b.dataset.src!=='rtsp'); document.getElementById('mp4-config').classList.toggle('hidden',b.dataset.src!=='mp4'); }); }); document.getElementById('btn-save').addEventListener('click',async()=>{ const src=document.querySelector('.src-btn.active').dataset.src; const rtsp=document.getElementById('rtsp-url').value; const mp4=document.getElementById('mp4-path').value; const w=document.getElementById('res-w').value||1920; const h=document.getElementById('res-h').value||1080; const f=document.getElementById('fps').value||30; await exec(`echo '{"source_type":"${src}","rtsp_url":"${rtsp}","mp4_path":"${mp4}","res_w":${w},"res_h":${h},"fps":${f}}' > /data/local/tmp/virtualcam_config.json`); log('Config saved','ok'); }); document.getElementById('btn-start').addEventListener('click',async()=>{ log('Starting provider...','info');await exec(CMD+' start');log('Provider started','ok');setTimeout(status,2000); }); document.getElementById('btn-stop').addEventListener('click',async()=>{ log('Stopping...','info');await exec(CMD+' stop');log('Stopped','ok');status(); }); document.getElementById('btn-feed').addEventListener('click',async()=>{ log('Starting feeder...','info');await exec(CMD+' start_feeder');log('Feeder started','ok');setTimeout(status,2000); }); document.getElementById('btn-unfeed').addEventListener('click',async()=>{ log('Stopping feeder...','info');await exec(CMD+' stop_feeder');log('Feeder stopped','ok');status(); }); document.getElementById('btn-refresh').addEventListener('click',status); });