1implement Mpeg; 2 3include "sys.m"; 4sys: Sys; 5FD: import Sys; 6include "draw.m"; 7draw: Draw; 8Display, Rect, Image: import draw; 9include "dial.m"; 10dial: Dial; 11Connection: import dial; 12include "mpeg.m"; 13 14Chroma: con 16r05; 15 16getenv() 17{ 18 if(sys != nil) 19 return; 20 21 sys = load Sys Sys->PATH; 22 draw = load Draw Draw->PATH; 23 dial = load Dial Dial->PATH; 24} 25 26copy(files: list of string, notify: chan of string, mpctl, mpdata: ref FD) 27{ 28 n: int; 29 c: ref Connection; 30 name: list of string; 31 32 while(files != nil) { 33 file := hd files; 34 (n, name) = sys->tokenize(file, "@"); 35 m : ref FD; 36 case n { 37 1 => 38 m = sys->open(file, sys->OREAD); 39 if(m == nil) { 40 notify <-= "mpeg open:" + file; 41 return; 42 } 43 2 => 44 c = dial->dial(hd tl name, nil); 45 if(c == nil) { 46 notify <-= "dial:" + hd tl name; 47 return; 48 } 49 sys->fprint(c.dfd, "%s\n", hd name); 50 c.cfd = nil; 51 m = c.dfd; 52 * => 53 notify <-= "bad file:"+hd name; 54 return; 55 } 56 sys->stream(m, mpdata, 64*1024); 57 files = tl files; 58 } 59 sys->fprint(mpctl, "stop"); 60 sys->fprint(mpctl, "window 0 0 0 0"); 61 notify <-= ""; 62} 63 64play(display: ref Display, w: ref Image, paint: int, r: Rect, file: string, notify: chan of string): string 65{ 66 i, j: int; 67 line: string; 68 cfg: array of byte; 69 buf := array[1024] of byte; 70 arg, words, files: list of string; 71 72 getenv(); 73 74 mpdata := sys->open("/dev/mpeg", sys->OWRITE); 75 if(mpdata == nil) 76 return sys->sprint("can't open /dev/mpeg: %r"); 77 78 obj := sys->open(file, sys->OREAD); 79 if(obj == nil) 80 return "open failed:"+file; 81 82 n := sys->read(obj, buf, len buf); 83 if(n < 0) 84 return "mpeg object: read error"; 85 86 mpctl := sys->open("/dev/mpegctl", sys->OWRITE); 87 if(mpctl == nil) 88 return "open mpeg ctl file"; 89 90 # Parse into lines 91 (n, arg) = sys->tokenize(string buf[0:n], "\n"); 92 for(i = 0; i < n; i++) { 93 # Parse into words 94 line = hd arg; 95 (j, words) = sys->tokenize(line, " \t"); 96 97 # Pass device config lines through to the ctl file 98 if(hd words == "files") 99 files = tl words; 100 else { 101 cfg = array of byte line; 102 if(sys->write(mpctl, cfg, len cfg) < 0) 103 return "invalid device config:"+line; 104 } 105 arg = tl arg; 106 } 107 108 if(files == nil) 109 return "no file to play"; 110 111 # now the driver is configured initialize the dsp's 112 # and set up the trident overlay 113 sys->fprint(mpctl, "init"); 114 sys->fprint(mpctl, "window %d %d %d %d", 115 r.min.x, r.min.y, r.max.x, r.max.y); 116 117 # paint the window with the chroma key color 118 if(paint) 119 w.draw(r, keycolor(display), nil, r.min); 120 121 if(notify != nil) { 122 spawn copy(files, notify, mpctl, mpdata); 123 return ""; 124 } 125 notify = chan of string; 126 spawn copy(files, notify, mpctl, mpdata); 127 return <-notify; 128} 129 130ctl(msg: string): int 131{ 132 mpc: ref FD; 133 134 getenv(); 135 136 mpc = sys->open("/dev/mpegctl", sys->OWRITE); 137 if(mpc == nil) 138 return -1; 139 140 b := array of byte msg; 141 n := sys->write(mpc, b, len b); 142 if(n != len b) 143 n = -1; 144 145 return n; 146} 147 148keycolor(display: ref Display): ref Image 149{ 150 getenv(); 151 return display.color(Chroma); 152} 153