code wiki / (root) / nx_media_player.nx

nx_media_player.nx source

↩ module page · 125 lines · 6535 B

1// nx_media_player.nx -- EXPOSURE rung X3: a privacy-respecting player/viewer. 2// "What am I watching" shown IN THE PLAYER (info panel), never in the URL. 3// Emits knowledge/staging/media/player.html: a stage (img/video by type) + an 4// info panel (title/type/resolution/person-present/skin, extensible to 5// face/preference/mood tags) + prev/next. The URL only ever holds an OPAQUE 6// index (#3) -- the filename/path lives in the in-page data + panel, so the 7// address bar leaks nothing. Metadata via the nx_media_index tagger. 8// 9// Sovereign: syscalls + nx_media_index. license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_media_index.nx" 12const K_MAGIC_4096: i64 = 4096 13const K_MAGIC_4095: i64 = 4095 14 15func gp(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 16func gnum(v: i64) -> i64 { 17 let bb: *u8 = sys_mmap(28) 18 var m: i64 = v 19 if m < 0 { sys_write(1, "-\x00" as *u8, 1); m = 0 - m } 20 let t: *u8 = sys_mmap(28) 21 var k: i64 = 0 22 if m == 0 { t[0] = 48 as u8; k = 1 } 23 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 24 var i: i64 = 0 25 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 26 sys_write(1, bb, k) 27 return 0 28} 29func fps(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 30func fnum(fd: i64, v: i64) -> i64 { 31 let bb: *u8 = sys_mmap(28) 32 var m: i64 = v 33 if m < 0 { sys_write(fd, "-\x00" as *u8, 1); m = 0 - m } 34 let t: *u8 = sys_mmap(28) 35 var k: i64 = 0 36 if m == 0 { t[0] = 48 as u8; k = 1 } 37 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 38 var i: i64 = 0 39 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 } 40 sys_write(fd, bb, k) 41 return 0 42} 43func strip_prefix(s: *u8, pre: *u8) -> i64 { 44 var i: i64 = 0 45 while pre[i] != (0 as u8) { if s[i] != pre[i] { return 0 } i = i + 1 } 46 return i 47} 48// write the basename (after the last '/') of a path to fd -- friendly title, 49// no directory leaked 50func fps_base(fd: i64, s: *u8) -> i64 { 51 var n: i64 = 0 52 var last: i64 = 0 - 1 53 while s[n] != (0 as u8) { if (s[n] as i64) == 47 { last = n } n = n + 1 } 54 var i: i64 = last + 1 55 while i < n { sys_write(fd, (s as i64 + i) as *u8, 1); i = i + 1 } 56 return 0 57} 58 59func main() -> i64 { 60 let szp: *i64 = sys_mmap(16) as *i64 61 let buf: *u8 = sys_read_file("knowledge/staging/media/idx_in.txt\x00" as *u8, szp) 62 if (buf as i64) == 0 { gp("nx_media_player: no idx_in.txt\n\x00" as *u8); return 1 } 63 let len: i64 = szp[0] 64 let fd: i64 = sys_openat_wr("knowledge/staging/media/player.html\x00" as *u8, 420) 65 if fd < 0 { gp("nx_media_player: cannot write html\n\x00" as *u8); return 2 } 66 67 fps(fd, "<!doctype html><html><head><meta charset=utf-8><title>Nishi Player</title><style>\x00" as *u8) 68 fps(fd, "body{background:#0c0c0c;color:#eee;font-family:sans-serif;margin:0;display:flex;height:100vh}\x00" as *u8) 69 fps(fd, "#stage{flex:1;display:flex;align-items:center;justify-content:center;background:#000}\x00" as *u8) 70 fps(fd, "#stage img,#stage video{max-width:100%;max-height:100vh}\x00" as *u8) 71 fps(fd, "#side{width:300px;padding:16px;background:#161616;overflow:auto}\x00" as *u8) 72 fps(fd, "#title{font-size:15px;font-weight:bold;word-break:break-all}.row{margin-top:8px;font-size:13px;color:#bbb}\x00" as *u8) 73 fps(fd, ".present{color:#39ff14;font-weight:bold}.absent{color:#888}.nav{margin-top:14px}button{background:#333;color:#eee;border:0;padding:6px 12px;margin-right:6px;cursor:pointer}\x00" as *u8) 74 fps(fd, "</style></head><body><div id=stage></div><div id=side><div id=title></div>\x00" as *u8) 75 fps(fd, "<div class=row id=meta></div><div class=row id=detect></div>\x00" as *u8) 76 fps(fd, "<div class=nav><button onclick=go(-1)>&larr; prev</button><button onclick=go(1)>next &rarr;</button></div>\x00" as *u8) 77 fps(fd, "<div class=row style=color:#555;margin-top:18px>URL stays opaque (index only); info lives here, not in the address bar.</div></div>\x00" as *u8) 78 fps(fd, "<script>var M=[\x00" as *u8) 79 80 let pbuf: *u8 = sys_mmap(K_MAGIC_4096) 81 let out: *i64 = sys_mmap(128) as *i64 82 var count: i64 = 0 83 var present: i64 = 0 84 var i: i64 = 0 85 while i < len { 86 var j: i64 = i 87 while j < len && (buf[j] as i64) != 10 { j = j + 1 } 88 var end: i64 = j 89 if end > i && (buf[end - 1] as i64) == 13 { end = end - 1 } 90 let ll: i64 = end - i 91 if ll > 0 { 92 var k: i64 = 0 93 while k < ll && k < K_MAGIC_4095 { pbuf[k] = buf[i + k]; k = k + 1 } 94 pbuf[k] = 0 as u8 95 nx_mindex_tag_path(pbuf, out) 96 if out[0] == NX_MIDX_OK { 97 if out[5] == 1 { present = present + 1 } 98 let off: i64 = strip_prefix(pbuf, "knowledge/staging/media/\x00" as *u8) 99 let src: *u8 = (pbuf as i64 + off) as *u8 100 fps(fd, "{n:\"\x00" as *u8); fps_base(fd, pbuf); fps(fd, "\",s:\"\x00" as *u8); fps(fd, src) 101 fps(fd, "\",t:\"image\",w:\x00" as *u8); fnum(fd, out[1]); fps(fd, ",h:\x00" as *u8); fnum(fd, out[2]) 102 fps(fd, ",p:\x00" as *u8); fnum(fd, out[5]); fps(fd, ",k:\x00" as *u8); fnum(fd, out[3]); fps(fd, "},\x00" as *u8) 103 count = count + 1 104 } 105 } 106 i = j + 1 107 } 108 109 fps(fd, "];var cur=0;function go(d){show(cur+d);}\x00" as *u8) 110 fps(fd, "function show(i){if(i<0)i=0;if(i>=M.length)i=M.length-1;cur=i;var m=M[i];\x00" as *u8) 111 fps(fd, "var st=document.getElementById('stage');\x00" as *u8) 112 fps(fd, "st.innerHTML=(m.t=='video')?('<video controls autoplay src=\"'+m.s+'\"></video>'):('<img src=\"'+m.s+'\">');\x00" as *u8) 113 fps(fd, "document.getElementById('title').textContent=m.n;\x00" as *u8) 114 fps(fd, "document.getElementById('meta').textContent=m.t+' '+m.w+'x'+m.h+' ('+(i+1)+'/'+M.length+')';\x00" as *u8) 115 fps(fd, "document.getElementById('detect').innerHTML=(m.p?'<span class=present>person present</span>':'<span class=absent>no person</span>')+' skin '+m.k+'permille';\x00" as *u8) 116 fps(fd, "location.hash=i;}\x00" as *u8) 117 fps(fd, "var h=parseInt(location.hash.slice(1));show(isNaN(h)?0:h);\x00" as *u8) 118 fps(fd, "</script></body></html>\n\x00" as *u8) 119 sys_close(fd) 120 121 gp("nx_media_player items=\x00" as *u8); gnum(count) 122 gp(" present=\x00" as *u8); gnum(present) 123 gp(" -> knowledge/staging/media/player.html (URL=opaque index; info in panel)\n\x00" as *u8) 124 return 0 125}