ColorTrixMovieCommandImpl:
CEDAR
PROGRAM
IMPORTS Args, CedarProcess, ColorTrixBasics, ColorTrixDispatch, ColorTrixFile, Controls, Process, Real, Terminal
~
BEGIN
ROPE: TYPE ~ Rope.ROPE;
PixelMap: TYPE ~ ColorTrixBasics.PixelMap;
PixelMapMisc: TYPE ~ ColorTrixBasics.PixelMapMisc;
DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle;
MovieData: TYPE ~ REF MovieDataRec;
MovieDataRec:
TYPE ~
MONITORED RECORD [
x, y, w, h, nFrames: NAT ← 0,
nRows, nCols: NAT ← 0,
speed, frame: Controls.Control ← NIL,
outer: Controls.Viewer ← NIL,
outerData: Controls.OuterData ← NIL,
frames, show, save: PixelMapMisc,
now: REAL ← 0.0,
nFrame: INTEGER ← 0,
pause, pauseSave: BOOL ← FALSE,
bounce: BOOL ← FALSE,
forward, forwardSave: BOOL ← TRUE
];
CtMovie:
PUBLIC Commander.CommandProc ~ {
ok: BOOL;
x, y, w, h, nFrames, clear, name: Args.Arg;
[ok, x, y, w, h, nFrames, clear, name] ← Args.ArgsGet[cmd, "%iiiii-clear%b-name%s"];
IF
NOT ok
THEN RETURN[$Failure, NIL]
ELSE {
cd: PixelMapMisc ← ColorTrixBasics.GetColorDisplayPmMisc[];
m: MovieData ← NEW[MovieDataRec];
m.x ← x.int;
m.y ← y.int;
m.w ← w.int;
m.h ← h.int;
m.nFrames ← nFrames.int;
m.show ← ColorTrixBasics.SetPmMiscWindow[cd, (cd.w-m.w)/2, (cd.h-m.h)/2, m.w, m.h];
IF name.ok
THEN {
m.frames ← ColorTrixFile.ReadFile[name.rope];
[m.nCols, m.nRows] ← NRowsCols[m.frames, m.nFrames, m.x, m.w];
}
ELSE {
[m.nCols, m.nRows] ← NRowsCols[cd, m.nFrames, m.x, m.w];
cd ← ColorTrixBasics.SetPmMiscWindow[
cd, 0, 0, m.nCols*m.w, MIN[cd.h, m.nRows*m.h]];
m.frames ← ColorTrixBasics.CreatePmMisc[cd.bpp, cd.x, cd.y, cd.w, cd.h];
ColorTrixBasics.CopyPmMisc[cd, m.frames];
};
m.speed ← Controls.NewControl["Speed", hSlider, m, -1.0, 1.0, 0.1,,,,,,,,,,,, LIST[[0.0, 0.0]]];
m.frame ← Controls.NewControl["Frame", hSlider, m, 0, nFrames.int-1,0, Frame,,TRUE];
m.outer ← Controls.OuterViewer[
data: m,
column: right,
name: "Ct Movie",
destroyProc: DestroyProc,
controls: LIST[m.speed, m.frame],
buttons: LIST [["Forward", Forward], ["Bounce-Off", Bounce], ["Pause", Pause]]
];
m.outerData ← NARROW[m.outer.data];
IF clear.ok AND clear.bool THEN ColorTrixBasics.FillPmMisc[cd];
ColorTrixBasics.CopyPmMisc[m.show, m.save ←
ColorTrixBasics.CreatePmMisc[cd.bpp, m.show.x, m.show.y, m.show.w, m.show.h]];
TRUSTED {Process.Detach[FORK Movie[m]]};
};
};
NRowsCols:
PROC [pm: PixelMapMisc, nFrames, x, w:
NAT]
RETURNS [nCols, nRows: NAT] ~ {
nCols ← MIN[nFrames, (pm.w-x)/w];
nRows ← nFrames/nCols+MIN[1, nFrames MOD nCols];
};
DestroyProc: Controls.DestroyProc ~ {NARROW[outerData.data, MovieData].pause ← FALSE};
ShowNFrame:
PROC [m: MovieData] ~ {
SetNFrame[m];
Terminal.WaitForBWVerticalRetrace[Terminal.Current[]];
ColorTrixBasics.CopyClippedPmMisc[
m.frames, m.show,
m.x+(m.nFrame MOD m.nCols)*m.w,
m.y+(m.nFrame/m.nCols)*m.h,
m.w, m.h];
IF NOT m.pause THEN Controls.SetSliderDialValue[m.frame, m.nFrame];
};
SetNFrame:
PROC [m: MovieData] ~ {
IF (m.nFrame ← Real.RoundI[m.now]) IN [0..m.nFrames) THEN RETURN;
IF m.bounce
THEN {
m.forward ← NOT m.forward;
m.nFrame ← IF m.nFrame < 0 THEN 0 ELSE m.nFrames-1;
}
ELSE {
IF m.nFrame >= m.nFrames THEN m.now ← m.nFrame ← 0;
IF m.nFrame < 0 THEN m.now ← m.nFrame ← m.nFrames-1;
};
};
Frame: Controls.ControlProc ~ {
m: MovieData ~ NARROW[control.data];
IF control.mouse.state = down THEN {m.pauseSave ← m.pause; m.pause ← TRUE};
m.now ← control.value;
ShowNFrame[m];
IF control.mouse.state = up THEN m.pause ← m.pauseSave;
};
Movie:
PROC [m: MovieData] ~ {
CedarProcess.SetPriority[background];
WHILE
NOT m.outerData.destroyed
DO
IF m.pause THEN {Process.Pause[Process.MsecToTicks[150]]; LOOP};
m.now ← m.now+(IF m.forward THEN m.speed.value ELSE -m.speed.value);
ShowNFrame[m];
ENDLOOP;
ColorTrixBasics.CopyPmMisc[m.save, m.show];
};
Pause: Controls.ClickProc ~ {
m: MovieData ~ NARROW[NARROW[clientData, Controls.OuterData].data];
m.pause ← NOT m.pause;
Controls.ButtonStyle[
m.outerData, "Pause", IF m.pause THEN $WhiteOnBlack ELSE $BlackOnWhite];
};
Bounce: Controls.ClickProc ~ {
m: MovieData ~ NARROW[NARROW[clientData, Controls.OuterData].data];
Controls.ButtonToggle[m.outerData, m.bounce ← NOT m.bounce, "Bounce-On", "Bounce-Off"];
IF m.bounce THEN m.forwardSave ← m.forward ELSE m.forward ← m.forwardSave;
};
Forward: Controls.ClickProc ~ {
m: MovieData ~ NARROW[NARROW[clientData, Controls.OuterData].data];
m.forward ← m.forwardSave ← NOT m.forward;
Controls.ButtonToggle[m.outerData, m.forward, "Forward", "Reverse"];
};