summaryrefslogtreecommitdiff
path: root/appl/grid/blurdemo.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/grid/blurdemo.b')
-rw-r--r--appl/grid/blurdemo.b977
1 files changed, 977 insertions, 0 deletions
diff --git a/appl/grid/blurdemo.b b/appl/grid/blurdemo.b
new file mode 100644
index 00000000..7688cd02
--- /dev/null
+++ b/appl/grid/blurdemo.b
@@ -0,0 +1,977 @@
+implement Blurdemo;
+
+include "sys.m";
+ sys : Sys;
+include "draw.m";
+ draw: Draw;
+ Display, Rect, Image: import draw;
+include "tk.m";
+ tk: Tk;
+include "tkclient.m";
+ tkclient: Tkclient;
+include "readdir.m";
+ readdir: Readdir;
+include "sh.m";
+include "registries.m";
+ registries: Registries;
+ Registry, Attributes, Service: import registries;
+include "grid/pathreader.m";
+ reader: PathReader;
+include "grid/browser.m";
+ browser: Browser;
+ Browse, Select, File, Parameter,
+ DESELECT, SELECT, TOGGLE: import browser;
+include "grid/srvbrowse.m";
+ srvbrowse: Srvbrowse;
+include "grid/announce.m";
+ announce: Announce;
+include "grid/readjpg.m";
+ readjpg: Readjpg;
+
+srvfilter: list of list of (string, string);
+currstep: int;
+
+currsrv: ref Service;
+currattach: ref Registries->Attached;
+ctxt: ref Draw->Context;
+display: ref Draw->Display;
+sysname : string;
+
+IMAGE: con 0;
+MOUNT: con 4;
+
+imgcache: ref Image;
+br: ref Browse;
+sel: ref Select;
+
+Blurdemo : module {
+ init : fn (context : ref Draw->Context, argv : list of string);
+ readpath: fn (dir: File): (array of ref sys->Dir, int);
+};
+
+init(context : ref Draw->Context, argv: list of string)
+{
+ ctxt = context;
+ display = ctxt.display;
+ sys = load Sys Sys->PATH;
+ if (sys == nil)
+ badmod(Sys->PATH);
+ readdir = load Readdir Readdir->PATH;
+ if (readdir == nil)
+ badmod(Readdir->PATH);
+ draw = load Draw Draw->PATH;
+ if (draw == nil)
+ badmod(Draw->PATH);
+ tk = load Tk Tk->PATH;
+ if (tk == nil)
+ badmod(Tk->PATH);
+ tkclient = load Tkclient Tkclient->PATH;
+ if (tkclient == nil)
+ badmod(Tkclient->PATH);
+ tkclient->init();
+ registries = load Registries Registries->PATH;
+ if (registries == nil)
+ badmod(Registries->PATH);
+ registries->init();
+ browser = load Browser Browser->PATH;
+ if (browser == nil)
+ badmod(Browser->PATH);
+ browser->init();
+ srvbrowse = load Srvbrowse Srvbrowse->PATH;
+ if (srvbrowse == nil)
+ badmod(Srvbrowse->PATH);
+ srvbrowse->init();
+ announce = load Announce Announce->PATH;
+ if (announce == nil)
+ badmod(Announce->PATH);
+ announce->init();
+ reader = load PathReader "$self";
+ if (reader == nil)
+ badmod("PathReader");
+ readjpg = load Readjpg Readjpg->PATH;
+ if (readjpg == nil)
+ badmod(Readjpg->PATH);
+ readjpg->init(display);
+ sys->pctl(sys->FORKNS | sys->NEWPGRP, nil);
+ if (ctxt == nil) {
+ sys->print("no draw context found!\n");
+ exit;
+ }
+ sysname = readfile("/dev/sysname");
+ if (sysname == "")
+ sysname = "Localhost";
+ imgcache = nil;
+ setsrvfilter();
+ root := "/";
+ currsrv = nil;
+
+ attribs := ("resource", "Cpu Pool") :: nil;
+ lcpupool := srvbrowse->find(attribs :: nil);
+ if (lcpupool == nil) {
+ browser->dialog(ctxt, nil, "ok" :: nil, "Alert","Cannot find a Cpu Pool Resource");
+ raise "fail: error cannot find a Cpu Pool resource";
+ }
+
+ (top, titlebar) := tkclient->toplevel(ctxt,"","BlurDemo", tkclient->Appl);
+ butchan := chan of string;
+ tk->namechan(top, butchan, "butchan");
+ browsechan := chan of string;
+ tk->namechan(top, browsechan, "browsechan");
+ selectchan := chan of string;
+ tk->namechan(top, selectchan, "selectchan");
+ br = Browse.new(top, "browsechan", "services/", "Services", 1, reader);
+ bropened := array[] of {
+ "services/",
+ "services/Data source/",
+ "services/Camera/",
+ "/n/remote/",
+ "/" ,
+ };
+ for (i := 0; i < len bropened; i++)
+ br.addopened(File (bropened[i], nil), 1);
+
+ sel = Select.new(top, "selectchan");
+
+ for (ik := 0; ik < len mainscreen; ik++)
+ tkcmd(top,mainscreen[ik]);
+
+ currstep = -1;
+
+ sel.addframe("image", "Select a '.bit' image");
+
+ changestep(top, IMAGE, nil);
+
+ tkcmd(top, "pack .f -fill both -expand 1; pack propagate . 0");
+ released := 1;
+ title := "";
+ resize(top, ref Rect ((0,0), (400,400)));
+ tkclient->onscreen(top, nil);
+ tkclient->startinput(top, "kbd"::"ptr"::nil);
+ tkpath: string;
+ selected := array[2] of File;
+ if (tl argv != nil)
+ spawn initimg(butchan, hd tl argv);
+
+ main: for (;;) {
+ alt {
+ s := <-top.ctxt.kbd =>
+ tk->keyboard(top, s);
+ s := <-top.ctxt.ptr =>
+ tk->pointer(top, *s);
+ inp := <-browsechan =>
+ (nil, lst) := sys->tokenize(inp, " \n\t");
+ if (len lst > 1)
+ tkpath = hd tl lst;
+ selected[0] = br.getselected(0);
+ selected[1] = br.getselected(1);
+ br.defaultaction(lst, nil);
+ i = -1;
+ if (!File.eq(selected[0], br.getselected(0)))
+ i = 0;
+ if (!File.eq(selected[1], br.getselected(1)))
+ i = 1;
+ if (i != -1) {
+ sel.select(sel.currfname,nil,DESELECT);
+ actionbutton(top, br.selected[i].file.path, br.selected[i].tkpath);
+ }
+ tkcmd(top, "update");
+ inp := <-selectchan =>
+ (nil, lst) := sys->tokenize(inp, " \n\t");
+ case hd lst {
+ "but3" =>
+ tkpath = hd tl lst;
+ x := string (int hd tl tl lst - 5);
+ y := string (int hd tl tl tl lst - 5);
+
+ path := tkcmd(top, tkpath+" cget -text");
+ s := blursrvc.attrs.get("name") + " ("+blursrvc.addr+")";
+ tk->cmd(top, "destroy .m2");
+ tkcmd(top, "menu .m2 -font /fonts/charon/plain.normal.font");
+ tkcmd(top, ".m2 add command -label {"+path+"}");
+ tkcmd(top, ".m2 add separator");
+ tkcmd(top, ".m2 add command -label {"+s+"}");
+ tkcmd(top, ".m2 post "+x+" "+y);
+ "double1" =>
+ tkpath = hd tl lst;
+ path := tkcmd(top, tkpath+" cget -text");
+ qid := "";
+ (n, nil) := sys->tokenize(path, "/");
+ if (currstep == IMAGE) {
+ qid = srvbrowse->getqid(blursrvc);
+ (res,name) := srvbrowse->getresname(blursrvc);
+ path = "services/"+res+"/"+name+"/";
+ }
+ else if (currsrv.addr != blursrvc.addr)
+ break;
+ else if (blursrvc.addr != "Local Machine")
+ path = "/n/remote" + path;
+ tkpath = br.gotoselectfile(File(path,qid));
+ if (tkpath != nil) {
+ sel.select(sel.currfname, nil, DESELECT);
+ actionbutton(top, path, tkpath);
+ }
+ "but1" =>
+ if (currstep == IMAGE)
+ br.selectfile(0, DESELECT, File (nil, nil), nil);
+ else
+ br.selectfile(1, DESELECT, File (nil, nil), nil);
+ sel.defaultaction(lst);
+ actionbutton(top, sel.getselected(sel.currfname), hd tl lst);
+ * =>
+ sel.defaultaction(lst);
+ }
+ tkcmd(top, "update");
+ inp := <-butchan =>
+ # sys->print("inp: %s\n",inp);
+ (nil, lst) := sys->tokenize(inp, " \n\t");
+ if (len lst > 1)
+ tkpath = hd tl lst;
+ case hd lst {
+ "refresh" =>
+ # ! check to see if anything is mounted first
+ if (currstep == IMAGE) {
+ # addlocalservice();
+ srvbrowse->refreshservices(srvfilter);
+ }
+ br.refresh();
+ "back" =>
+ changestep(top, IMAGE, nil);
+ "run" =>
+ spawn run(ctxt, getcoords(top));
+ "preview" =>
+ spawn previewwin(top, butchan, hd tl lst);
+ "add" =>
+ additem(top, hd tl lst, int hd tl tl lst);
+ "del" =>
+ sel.delselection("image", hd tl lst);
+ tkcmd (top, ".f.ftop.bn configure -state disabled");
+ blurimage = nil;
+ blurtkpath = nil;
+ blursrvc = nil;
+ actionbutton(top, sel.getselected(sel.currfname), hd tl lst);
+ "mount" =>
+ file := br.getpath(tkpath);
+ (nsrv, lsrv) := sys->tokenize(file.path, "/");
+ if (currstep != IMAGE)
+ break;
+ if (nsrv != 3)
+ break;
+ if (hd tl tl lsrv != "Local Filestore") {
+ ok := mountsrv(file.path, file.qid, getcoords(top));
+ if (!ok)
+ break;
+ changestep(top, MOUNT, hd tl tl lsrv);
+ }
+ else {
+ srv : Service;
+ srv.attrs = Attributes.new(("name", sysname) :: nil);
+ srv.addr = "Local Machine";
+ currsrv = ref srv;
+ changestep(top, MOUNT, hd tl tl lsrv);
+ }
+ }
+ tkcmd(top, "update");
+
+ title = <-top.ctxt.ctl or
+ title = <-top.wreq or
+ title = <-titlebar =>
+ if (title == "exit")
+ break main;
+ e := tkclient->wmctl(top, title);
+ if (e == nil && title[0] == '!') {
+ (nil, lst) := sys->tokenize(title, " \t\n");
+ if (len lst >= 2 && hd lst == "!size" && hd tl lst == ".")
+ resize(top, nil);
+ }
+ }
+ }
+ currattach = nil;
+ killg(sys->pctl(0,nil));
+}
+
+resize(top: ref Tk->Toplevel, r: ref Draw->Rect)
+{
+ if (r != nil) {
+ sw := (*r).dx();
+ sh := (*r).dy();
+ ww := int tkcmd(top, ". cget -actwidth");
+ wh := int tkcmd(top, ". cget -actheight");
+ if (ww > sw)
+ tkcmd(top, ". configure -x 0 -width "+string sw);
+ if (wh > sh)
+ tkcmd(top, ". configure -y 0 -height "+string sh);
+ }
+ w := int tkcmd(top, ".fselect cget -actwidth");
+ h := int tkcmd(top, ".fselect cget -actheight");
+ sel.resize(w,h);
+}
+
+nactionbuttons := 0;
+actionbutton(top: ref Tk->Toplevel, path, tkpath: string)
+{
+ for (i := 0; i < nactionbuttons; i++) {
+ tkcmd(top, "grid forget .f.ftop.baction"+string i);
+ tkcmd(top, "destroy .f.ftop.baction"+string i);
+ }
+ if (path == nil) {
+ nactionbuttons = 0;
+ return;
+ }
+ buttons : list of (string,string) = nil;
+ (n, nil) := sys->tokenize(path, "/");
+ if (len tkpath > 8 && tkpath[:8] == ".fselect")
+ buttons = ("Remove", "del "+tkpath) :: buttons;
+ else {
+ if (currstep == IMAGE) {
+ if (n == 3)
+ buttons = ("Mount", "mount "+tkpath) :: buttons;
+ }
+ else {
+ if (len path > 4) {
+ if (path[len path - 4:] == ".bit") {
+ buttons = ("Select", "add "+path+" 0") ::
+ ("Preview", "preview "+path) :: buttons;
+ }
+ else if (path[len path - 4:] == ".jpg")
+ buttons = ("Select", "add "+path+" 0") :: buttons;
+ }
+ }
+ }
+ nactionbuttons = len buttons;
+ for (i = 0; i < nactionbuttons; i++) {
+ name := ".f.ftop.baction"+string i+" ";
+ (text,cmd) := hd buttons;
+ tkcmd(top, "button "+name+"-text {"+text+"} "+
+ "-font /fonts/charon/bold.normal.font "+
+ "-command {send butchan "+cmd+"}");
+ tkcmd(top, "grid "+name+" -row 0 -column "+string (4+i));
+ buttons = tl buttons;
+ }
+}
+
+initimg(butchan: chan of string, imgpath: string)
+{
+ srv : Service;
+ srv.attrs = Attributes.new(("name", sysname) :: nil);
+ srv.addr = "Local Machine";
+ currsrv = ref srv;
+ butchan <-= "add "+imgpath+" 0";
+ butchan <-= "back";
+}
+
+blurimage := "";
+blurtkpath := "";
+blursrvc: ref Service;
+
+additem(top: ref Tk->Toplevel, path: string, overwrite: int)
+{
+ if (blurimage != nil) {
+ if (overwrite || browser->dialog(ctxt, top, "ok" :: "cancel" :: nil,
+ "Alert","Replace existing image '"
+ +nopath(blurimage)+"' with '"+nopath(path)+"'?") == 0) {
+ sel.delselection("image", blurtkpath);
+ }
+ else
+ return;
+ }
+ imgpath := path;
+ if (currsrv.addr != "Local Machine")
+ path = path[len "/n/remote":];
+ blurtkpath = sel.addselection("image", path, nil, 0);
+ tkcmd(top, "update");
+ blurimage = path;
+ blursrvc = currsrv;
+ if (overwrite)
+ spawn getpreview(blurtkpath, nil, imgcache);
+ else
+ spawn getpreview(blurtkpath, imgpath, nil);
+}
+
+nopath(file: string): string
+{
+ return file[len browser->prevpath(file):];
+}
+
+runscr := array[] of {
+ "frame .f",
+ "frame .f.f1",
+ "label .f.f1.l -text {Select no of CPUs} -font /fonts/charon/plain.normal.font",
+ "scale .f.f1.s -orient horizontal -height 16 -showvalue 0 -from 1 -to 20 -command {.f.f1.ls configure -text}",
+ "label .f.f1.ls -text {1} -font /fonts/charon/plain.normal.font -width 30",
+ "button .f.f1.b -text {Run} -font /fonts/charon/plain.normal.font -command {send butchan go}",
+ "pack .f.f1.l .f.f1.s .f.f1.ls .f.f1.b -side left",
+ "frame .f.f2",
+ "text .f.f2.t -width 250 -height 150 -borderwidth 1 -bg white -font /fonts/charon/plain.normal.font -yscrollcommand { .f.f2.sy set }",
+ "scrollbar .f.f2.sy -command { .f.f2.t yview }",
+ "pack .f.f2.sy -side left -fill y",
+ "pack .f.f2.t -fill both -expand 1",
+ "bind .Wm_t <Button-1> +{focus .Wm_t}",
+ "bind .Wm_t.title <Button-1> +{focus .Wm_t}",
+ "focus .Wm_t",
+ "pack .f.f1 -side top",
+ "pack .f.f2 -fill both -expand 1",
+};
+
+run(ctxt: ref Draw->Context, coords: draw->Rect)
+{
+ (top, titlectl) := tkclient->toplevel(ctxt, "", nil, tkclient->Resize);
+ butchan := chan of string;
+ sync := chan of int;
+ quit := chan of int;
+ tk->namechan(top, butchan, "butchan");
+ tkcmds(top, runscr);
+ tkcmd(top, ". configure "+getcentre(top, coords));
+ tkcmd(top, "pack .f -fill both -expand 1; pack propagate . 0; focus .; update");
+ tkclient->onscreen(top, "exact");
+ tkclient->startinput(top, "kbd"::"ptr"::nil);
+ done := 1;
+ loop: for (;;) {
+ alt {
+ s := <-top.ctxt.kbd =>
+ tk->keyboard(top, s);
+ s := <-top.ctxt.ptr =>
+ tk->pointer(top, *s);
+ <-sync =>
+ tkcmd(top, ".f.f1.b configure -state normal; update");
+ done = 1;
+ inp := <-butchan =>
+ (nil, lst) := sys->tokenize(inp, " \n\t");
+ case hd lst {
+ "go" =>
+ tkcmd(top, ".f.f1.b configure -state disabled");
+ ncpus := int tkcmd(top, ".f.f1.s get");
+ done = 0;
+ spawn startit(ncpus, butchan, sync, quit);
+ "output" =>
+ tkcmd(top, ".f.f2.t insert end {"+inp[len "output ":]+"}");
+ "error" =>
+ tkcmd(top, ".f.f2.t insert end {Error: "+inp[len "error ":]+"\n}");
+ tkcmd(top, ".f.f1.b configure -state normal");
+ "fewcpu" =>
+ i := browser->dialog(ctxt, top, "ok" :: "cancel" :: nil, "Alert",
+ "Only found "+hd tl lst+" cpus available. Continue?");
+ quit <-= i;
+ if (i == 1)
+ return;
+ }
+ tkcmd(top, "update");
+ s := <-top.ctxt.ctl or
+ s = <-top.wreq or
+ s = <- titlectl =>
+ if (s == "exit") {
+ if (done)
+ return;
+ break loop;
+ }
+ else
+ tkclient->wmctl(top, s);
+ }
+ }
+ top = nil;
+ for (;;) alt {
+ <- butchan =>
+ ;
+ <-sync =>
+ return;
+ }
+}
+
+startit(ncpus: int, butchan: chan of string, sync, quit: chan of int)
+{
+ imgattached : ref Registries->Attached;
+ imgpath := blurimage;
+ if (blursrvc.addr != "Local Machine") {
+ imgattached = blursrvc.attach(nil, nil);
+ if (imgattached == nil) {
+ butchan <-= "error cannot connect to data source: "+blursrvc.attrs.get("name");
+ return;
+ }
+ if (sys->mount(imgattached.fd, nil, "/n/local", sys->MREPL, nil) == -1) {
+ butchan <-= sys->sprint("error img mount failed: %r");
+ return;
+ }
+ imgpath = "/n/local" + imgpath;
+ butchan <-= "output Found image namespace\n";
+ }
+ sys->pctl(sys->FORKNS, nil);
+ attribs := ("resource", "Cpu Pool") :: nil;
+ lsrv := srvbrowse->find(attribs :: nil);
+ if (lsrv == nil) {
+ butchan <-= "error cannot find Cpu Pool resource";
+ return;
+ }
+ cpupoolsrvc := hd lsrv;
+ attached := cpupoolsrvc.attach(nil, nil);
+ if (attached == nil) {
+ butchan <-= "error cannot connect to Cpu Pool resource";
+ return;
+ }
+ if (sys->mount(attached.fd, nil, "/n/remote", sys->MREPL, nil) == -1) {
+ butchan <-= sys->sprint("error Cpu Pool mount failed: %r");
+ return;
+ }
+ butchan <-= "output Connected to Cpu Pool resource\n";
+ if (blurimage[len blurimage - 4:] == ".jpg") {
+ butchan <-= "output Converting jpg => bit image\n";
+ chanin := chan of string;
+ killchan := chan of int;
+ spawn jpgprog(butchan, chanin, killchan);
+ img := readjpg->jpg2img(imgpath, "", chan of string, chanin);
+ killchan <-= 1;
+ butchan <-= "output \n";
+ if (img == nil) {
+ butchan <-= "error Error converting jpg";
+ return;
+ }
+ sys->remove("/n/remote/data/blurimage.bit");
+ fd := sys->create("/n/remote/data/blurimage.bit", sys->OWRITE, 8r666);
+ if (fd == nil || display.writeimage(fd, img) == -1) {
+ butchan <-= sys->sprint("error Error saving bit: %r");
+ return;
+ }
+ imgpath = "/n/remote/data/blurimage.bit";
+ }
+ afd := array[ncpus] of ref sys->FD;
+ ngot := 0;
+ for (i := 0; i < ncpus; i++) {
+ afd[ngot] = sys->open("/n/remote/clone", sys->ORDWR);
+ if (afd[ngot] == nil)
+ break;
+ ngot++;
+ }
+ if (ngot == 0) {
+ butchan <-= "error no cpu resources available";
+ return;
+ }
+ if (ngot < ncpus) {
+ butchan <-= "fewcpu "+string ngot;
+ q := <-quit;
+ if (q)
+ return;
+ }
+ butchan <-= "output Found "+string ngot+" Cpu resource(s)\n";
+ sh := load Sh Sh->PATH;
+ if (sh == nil)
+ badmod(Sh->PATH);
+ sys->create("/n/remote/data/blur", sys->OREAD, 8r777 | sys->DMDIR);
+ done := chan of int;
+ for (i = 0; i < ngot; i++)
+ spawn go(afd[i], i, butchan, done);
+ err := sh->run(ctxt, "/dis/grid/demo/blur.dis" :: "/n/remote/data" :: imgpath :: nil);
+ if (err != nil)
+ butchan <-= "error "+err;
+ finished := 0;
+ for (;;) {
+ <-done;
+ finished++;
+ if (finished == ngot)
+ break;
+ }
+ sys->unmount(nil, "/n/remote");
+ butchan <-= "output Finished\n";
+ sync <-= 1;
+}
+
+jpgprog(butchan, chanin: chan of string, killchan: chan of int)
+{
+ i := 0;
+ for (;;) alt {
+ <-killchan =>
+ return;
+ <-chanin =>
+ i = (i+1) % 2;
+ if (i)
+ butchan <-= "output .";
+ }
+}
+
+go(fd: ref sys->FD, id: int, butchan: chan of string, done: chan of int)
+{
+ op := "output Cpu "+string id+": ";
+ sys->fprint(fd, "/dis/grid/demo/blur.dis /data/");
+ buf := array[sys->ATOMICIO] of byte;
+ sys->seek(fd, big 0, sys->SEEKSTART);
+ i := sys->read(fd, buf, len buf);
+ if (i < 1)
+ sys->print("Error reading dir name: %r\n");
+ dir := string buf[:i];
+ if (dir[len dir - 1] == '\n')
+ dir = dir[:len dir -1];
+ fdout := sys->open("/n/remote/"+dir+"/data", sys->OREAD);
+ if (fdout == nil) {
+ butchan <-= op+"Cannot read from stdout";
+ done <-= 1;
+ return;
+ }
+ for (;;) {
+ i = sys->read(fdout, buf, len buf);
+ if (i < 1)
+ break;
+ s := string buf[:i];
+ if (s[len s - 1] != '\n')
+ s[len s] = '\n';
+ butchan <-= op+s;
+ }
+ done <-= 1;
+}
+
+kill(pid: int)
+{
+ if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil)
+ sys->fprint(fd, "kill");
+}
+
+killg(pid: int)
+{
+ if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil)
+ sys->fprint(fd, "killgrp");
+}
+
+mainscreen := array[] of {
+ "frame .f",
+ "frame .f.ftop",
+ "variable opt command",
+ "button .f.ftop.bp -text {Services} -command {send butchan back} -font /fonts/charon/bold.normal.font -state disabled -state disabled",
+ "button .f.ftop.bn -text {Run} -command {send butchan run} -font /fonts/charon/bold.normal.font -state disabled",
+ "button .f.ftop.br -text {Refresh} -command {send butchan refresh} -font /fonts/charon/bold.normal.font",
+ "grid .f.ftop.br .f.ftop.bp .f.ftop.bn -row 0",
+ "grid columnconfigure .f.ftop 3 -minsize 30",
+ "label .f.l -text { } -height 1 -bg red",
+ "grid .f.l -row 1 -column 0 -sticky ew",
+ "grid .f.ftop -row 0 -column 0 -pady 2 -sticky w",
+ "grid .fbrowse -in .f -row 2 -column 0 -sticky nsew",
+ "grid .fselect -in .f -row 3 -column 0 -sticky nsew",
+ "grid columnconfigure .f 0 -weight 1",
+ "grid rowconfigure .f 2 -weight 1",
+ "grid rowconfigure .f 3 -weight 1",
+
+ "bind .Wm_t <Button-1> +{focus .Wm_t}",
+ "bind .Wm_t.title <Button-1> +{focus .Wm_t}",
+ "focus .Wm_t",
+};
+
+readpath(dir: File): (array of ref sys->Dir, int)
+{
+ if (currstep == MOUNT) {
+ (dirs, nil) := readdir->init(dir.path, readdir->NAME | readdir->COMPACT);
+ dirs2 := array[len dirs] of ref sys->Dir;
+ num := 0;
+ for (i := 0; i < len dirs; i++)
+ if (dirs[i].mode & sys->DMDIR ||
+ (len dirs[i].name > 4 && (
+ dirs[i].name[len dirs[i].name - 4:] == ".bit" ||
+ dirs[i].name[len dirs[i].name - 4:] == ".jpg")))
+ dirs2[num++] = dirs[i];
+ return (dirs2[:num], 0);
+ }
+ else
+ return srvbrowse->servicepath2Dir(dir.path, int dir.qid);
+ return (nil, 0);
+}
+
+badmod(path: string)
+{
+ sys->print("Blurdemo: failed to load %s: %r\n",path);
+ exit;
+}
+
+mountscr := array[] of {
+ "frame .f -borderwidth 2 -relief raised",
+ "text .f.t -width 200 -height 60 -borderwidth 1 -bg white -font /fonts/charon/plain.normal.font",
+ "button .f.b -text {Cancel} -command {send butchan cancel} -width 70 -font /fonts/charon/plain.normal.font",
+ "grid .f.t -row 0 -column 0 -padx 10 -pady 10",
+ "grid .f.b -row 1 -column 0 -sticky n",
+ "grid rowconfigure .f 1 -minsize 30",
+};
+
+mountsrv(srvpath, qid: string, coords: draw->Rect):int
+{
+ (top, nil) := tkclient->toplevel(ctxt, "", nil, tkclient->Plain);
+ ctlchan := chan of string;
+ butchan := chan of string;
+ tk->namechan(top, butchan, "butchan");
+ tkcmds(top, mountscr);
+ tkcmd(top, ". configure "+getcentre(top, coords)+"; pack .f; update");
+ spawn mountit(srvpath, qid, ctlchan);
+ pid := int <-ctlchan;
+ tkclient->onscreen(top, "exact");
+ tkclient->startinput(top, "kbd"::"ptr"::nil);
+ for (;;) {
+ alt {
+ s := <-top.ctxt.kbd =>
+ tk->keyboard(top, s);
+ s := <-top.ctxt.ptr =>
+ tk->pointer(top, *s);
+ e := <- ctlchan =>
+ if (e[0] == '!') {
+ tkcmd(top, ".f.t insert end {"+e[1:]+"}");
+ tkcmd(top, ".f.b configure -text {close}; update");
+ pid = -1;
+ }
+ else if (e == "ok")
+ return 1;
+ else
+ tkcmd(top, ".f.t insert end {"+e+"}; update");
+ <- butchan =>
+ if (pid != -1)
+ kill(pid);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+mountit(srvpath, qid: string, ctlchan: chan of string)
+{
+ ctlchan <-= string sys->pctl(0,nil);
+
+ n := 0;
+ (nil, lst) := sys->tokenize(srvpath, "/");
+ stype := hd tl lst;
+ name := hd tl tl lst;
+ addr := "";
+ ctlchan <-= "Connecting...\n";
+ lsrv := srvbrowse->servicepath2Service(srvpath, qid);
+ if (len lsrv < 1) {
+ ctlchan <-= "!could not find service";
+ return;
+ }
+ srvc := hd lsrv;
+ currattach = srvc.attach(nil, nil);
+ if (currattach == nil) {
+ ctlchan <-= "!attach failed";
+ return;
+ }
+ ctlchan <-= "Mounting...\n";
+ if (sys->mount(currattach.fd, nil, "/n/remote", sys->MREPL, nil) != -1) {
+ ctlchan <-= "ok";
+ currsrv = srvc;
+ }
+ else
+ ctlchan <-= "!mount failed";
+}
+
+getcoords(top: ref Tk->Toplevel): draw->Rect
+{
+ h := int tkcmd(top, ". cget -height");
+ w := int tkcmd(top, ". cget -width");
+ x := int tkcmd(top, ". cget -actx");
+ y := int tkcmd(top, ". cget -acty");
+ r := draw->Rect((x,y),(x+w,y+h));
+ return r;
+}
+
+getcentre(top: ref Tk->Toplevel, winr: draw->Rect): string
+{
+ h := int tkcmd(top, ".f cget -height");
+ w := int tkcmd(top, ".f cget -width");
+ midx := winr.min.x + (winr.dx() / 2);
+ midy := winr.min.y + (winr.dy() / 2);
+ newx := midx - (w/2);
+ newy := midy - (h/2);
+ return "-x "+string newx+" -y "+string newy;
+}
+
+changestep(top: ref Tk->Toplevel, step: int, label: string)
+{
+ root, rlabel: string;
+ if (step == MOUNT) {
+ tkcmd (top, ".f.ftop.bp configure -state normal");
+ br.changeview(2);
+ rlabel = label;
+ if (currsrv.addr == "Local Machine")
+ root = "/";
+ else
+ root = "/n/remote/";
+ }
+ else if (step == IMAGE) {
+ br.changeview(1);
+ if (currsrv != nil) {
+ sys->unmount(nil, "/n/remote");
+ currattach = nil;
+ currsrv = nil;
+ }
+ srvbrowse->refreshservices(srvfilter);
+ root = "services/";
+ rlabel = "Image Services";
+ sel.showframe("image");
+ tkcmd (top, ".f.ftop.bp configure -state disabled");
+ # addlocalservice();
+ sel.select("image", nil, DESELECT);
+ }
+ currstep = step;
+ br.selectfile(1, DESELECT, File (nil, nil), nil);
+ br.selectfile(0, DESELECT,File (nil, nil), nil);
+ actionbutton(top, nil, nil);
+
+ br.newroot(root, rlabel);
+ if (currstep == MOUNT)
+ br.selectfile(0, SELECT, File (root, nil), ".fbrowse.fl.f0.l");
+ tkcmd(top, "update");
+}
+
+addlocalservice()
+{
+ lsrv : Service;
+ attrs := ("resource", "Data source") ::
+ ("name", "Local Filestore") ::
+ ("type", "styx") :: nil;
+ lsrv.attrs = Attributes.new(attrs);
+ lsrv.addr = "@your local filestore";
+ srvbrowse->addservice(ref lsrv);
+}
+
+tkcmd(top: ref Tk->Toplevel, cmd: string): string
+{
+ e := tk->cmd(top, cmd);
+ if (e != "" && e[0] == '!')
+ sys->print("Tk error: '%s': %s\n",cmd,e);
+ return e;
+}
+
+tkcmds(top: ref Tk->Toplevel, a: array of string)
+{
+ for (j := 0; j < len a; j++)
+ tkcmd(top, a[j]);
+}
+
+readfile(f: string): string
+{
+ fd := sys->open(f, sys->OREAD);
+ if(fd == nil)
+ return nil;
+
+ buf := array[8192] of byte;
+ n := sys->read(fd, buf, len buf);
+ if(n < 0)
+ return nil;
+
+ return string buf[:n];
+}
+
+setsrvfilter()
+{
+ imagefilter := ("proto", "styx") :: ("auth", "none") :: ("Image resource", "1") :: nil;
+ srvfilter = imagefilter :: nil;
+}
+
+getpreview(tkpath, imgpath: string, img: ref Image)
+{
+ if (imgpath != nil && imgpath[len imgpath - 4:] == ".jpg") {
+ tkcmd (sel.top, ".f.ftop.bn configure -state normal");
+ return;
+ }
+ if (img == nil) {
+ img = display.open(imgpath);
+ if (img == nil) {
+ browser->dialog(ctxt, sel.top, "ok" :: nil, "Alert",
+ sys->sprint("Invalid '.bit' image: %r"));
+ sel.delselection("image", blurtkpath);
+ blurimage = nil;
+ blursrvc = nil;
+ return;
+ }
+ }
+ previmg := preview(img, 100);
+ tk->cmd(sel.top, "destroy .preview");
+ tkcmd(sel.top, "image create bitmap .preview");
+ tk->putimage(sel.top, ".preview", previmg, nil);
+ tkcmd(sel.top, sys->sprint("%s configure -image .preview -width %d -height %d",
+ tkpath, previmg.r.dx(), previmg.r.dy()));
+ tkcmd(sel.top, "grid forget "+tkpath+"; grid "+tkpath+" -row 1 "+
+ "-column 0 -columnspan 3 -pady 5 -sticky ew;");
+ sel.setscrollr(sel.currfname);
+ tkcmd (sel.top, ".f.ftop.bn configure -state normal");
+ tkcmd(sel.top, "update;");
+}
+
+preview(img: ref Image, maxsize: int): ref Image
+{
+ mx := max(img.r.dx(), img.r.dy());
+ if (mx <= maxsize) {
+ imgcache = img;
+ return img;
+ }
+ prevr := Rect ((0,0), (img.r.dx()*maxsize/mx, img.r.dy()*maxsize/mx));
+ tmpimg := display.newimage(img.r, Draw->RGB24, 0, Draw->White);
+ previmg := display.newimage(prevr, Draw->RGB24, 0, Draw->White);
+ tmpimg.draw(img.r, img, nil, (0,0));
+
+ getr := Rect ((0,0), (img.r.dx() / prevr.dx(), img.r.dy() / prevr.dy()));
+
+ nopixels := getr.dx() * getr.dy();
+ getrgb := array[nopixels * 3] of byte;
+ newrgb := array[3] of byte;
+ for (y := 0; y < prevr.dy(); y++) {
+ for (x := 0; x < prevr.dx(); x++) {
+ tmpimg.readpixels(getr.addpt((x*getr.dx(), y*getr.dy())), getrgb);
+ tmprgb := array[] of { 0, 0, 0 };
+ for (i := 0; i < len getrgb; i++)
+ tmprgb[i%3] += int getrgb[i];
+ for (i = 0; i < 3; i++)
+ newrgb[i] = byte (tmprgb[i] / nopixels);
+ previmg.writepixels(((x,y),(x+1,y+1)), newrgb);
+ }
+ }
+ imgcache = previmg;
+ return previmg;
+}
+
+max(a,b: int): int
+{
+ if (a > b)
+ return a;
+ return b;
+}
+
+previewscr := array[] of {
+ "frame .f",
+ "panel .f.p -borderwidth 2 -relief raised",
+ "button .f.bs -text Select -font /fonts/charon/plain.normal.font -command {send prevchan select} -state disabled",
+ "button .f.bc -text Close -font /fonts/charon/plain.normal.font -command {send prevchan close} -state disabled",
+ "pack .f",
+ "grid .f.p -row 0 -column 0 -columnspan 2 -padx 5 -pady 5",
+ "grid .f.bs .f.bc -row 1 -padx 5 -pady 5",
+ "update",
+};
+
+previewwin(oldtop: ref Tk->Toplevel, chanout: chan of string, path: string)
+{
+ (top, titlectl) := tkclient->toplevel(ctxt, "", "Loading...", 0);
+ prevchan := chan of string;
+ tk->namechan(top, prevchan, "prevchan");
+ tkclient->onscreen(top, "exact");
+
+ img := display.open(path);
+ if (img == nil) {
+ browser->dialog(ctxt, oldtop, "ok" :: nil, "Alert", "Invalid '.bit' image");
+ return;
+ }
+
+ previmg := preview(img, 100);
+ tkcmds(top, previewscr);
+ tk->putimage(top, ".f.p", previmg, nil);
+ tkcmd(top, ".Wm_t.title configure -text Preview");
+ tkcmd(top, ".f.p dirty; update");
+ browser->setcentre(oldtop, top);
+ tkcmd(top, ".f.bs configure -state normal; .f.bc configure -state normal");
+ tkclient->startinput(top, "kbd"::"ptr"::nil);
+
+ main: for(;;) alt {
+ s := <-top.ctxt.kbd =>
+ tk->keyboard(top, s);
+ s := <-top.ctxt.ptr =>
+ tk->pointer(top, *s);
+ s := <- prevchan =>
+ if (s == "select")
+ chanout <-= "add "+path+" 1";
+ break main;
+ s := <-top.ctxt.ctl or
+ s = <-top.wreq or
+ s = <- titlectl =>
+ if (s == "exit")
+ break main;
+ else
+ tkclient->wmctl(top, s);
+ }
+}