xref: /haiku/src/add-ons/screen_savers/ifs/IFSSaver.cpp (revision 90ae2e54f6ccaca73c011a2aa4cdd660417108ad)
1 // IFSSaver.cpp
2 
3 
4 #include <math.h>
5 #include <stdio.h>
6 
7 #include <Catalog.h>
8 #include <CheckBox.h>
9 #include <Slider.h>
10 #include <TextView.h>
11 
12 #include "IFSSaver.h"
13 
14 #undef B_TRANSLATION_CONTEXT
15 #define B_TRANSLATION_CONTEXT "Screensaver IFS"
16 
17 
18 enum {
19 	MSG_TOGGLE_ADDITIVE		= 'tgad',
20 	MSG_SET_SPEED			= 'stsp',
21 };
22 
23 // MAIN INSTANTIATION FUNCTION
24 extern "C" _EXPORT BScreenSaver*
25 instantiate_screen_saver(BMessage *message, image_id image)
26 {
27 	return new IFSSaver(message, image);
28 }
29 
30 // constructor
31 IFSSaver::IFSSaver(BMessage *message, image_id id)
32 	: BScreenSaver(message, id),
33 	  BHandler("IFS Saver"),
34 	  fIFS(NULL),
35 	  fIsPreview(false),
36 	  fBounds(0.0, 0.0, -1.0, -1.0),
37 	  fLastDrawnFrame(0),
38 	  fAdditive(false),
39 	  fSpeed(6)
40 {
41 	fDirectInfo.bits = NULL;
42 	fDirectInfo.bytesPerRow = 0;
43 
44 	if (message) {
45 		if (message->FindBool("IFS additive", &fAdditive) < B_OK)
46 			fAdditive = false;
47 		if (message->FindInt32("IFS speed", &fSpeed) < B_OK)
48 			fSpeed = 6;
49 	}
50 }
51 
52 // destructor
53 IFSSaver::~IFSSaver()
54 {
55 	if (Looper()) {
56 		Looper()->RemoveHandler(this);
57 	}
58 	_Cleanup();
59 }
60 
61 // StartConfig
62 void
63 IFSSaver::StartConfig(BView *view)
64 {
65 	BRect bounds = view->Bounds();
66 	bounds.InsetBy(10.0, 10.0);
67 	BRect frame(0.0, 0.0, bounds.Width(), 20.0);
68 
69 	// the additive check box
70 	fAdditiveCB = new BCheckBox(frame, "additive setting",
71 								B_TRANSLATE("Render dots additive"),
72 								new BMessage(MSG_TOGGLE_ADDITIVE),
73 								B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
74 
75 	fAdditiveCB->SetValue(fAdditive);
76 
77 	fAdditiveCB->ResizeToPreferred();
78 	bounds.bottom -= fAdditiveCB->Bounds().Height() * 2.0;
79 	fAdditiveCB->MoveTo(bounds.LeftBottom());
80 
81 	view->AddChild(fAdditiveCB);
82 
83 	// the additive check box
84 	fSpeedS = new BSlider(frame, "speed setting",
85 						  B_TRANSLATE("Morphing speed:"),
86 						  new BMessage(MSG_SET_SPEED),
87 						  1, 12, B_BLOCK_THUMB,
88 						  B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM);
89 
90 	fSpeedS->SetValue(fSpeed);
91 	fSpeedS->SetHashMarks(B_HASH_MARKS_BOTTOM);
92 	fSpeedS->SetHashMarkCount(12);
93 
94 	fSpeedS->ResizeToPreferred();
95 	bounds.bottom -= fSpeedS->Bounds().Height() + 15.0;
96 	fSpeedS->MoveTo(bounds.LeftBottom());
97 
98 	view->AddChild(fSpeedS);
99 
100 	// the info text view
101 	BRect textRect = bounds;
102 	textRect.OffsetTo(0.0, 0.0);
103 	BTextView* textView = new BTextView(bounds, B_EMPTY_STRING, textRect,
104 										B_FOLLOW_ALL, B_WILL_DRAW);
105 	textView->SetViewColor(view->ViewColor());
106 
107 	BString aboutScreenSaver(B_TRANSLATE("%screenSaverName%\n\n"
108 					 ""B_UTF8_COPYRIGHT" 1997 Massimino Pascal\n\n"
109 					 "xscreensaver port by Stephan Aßmus\n"
110 					 "<stippi@yellowbites.com>"));
111 	BString screenSaverName(B_TRANSLATE("Iterated Function System"));
112 
113 	aboutScreenSaver.ReplaceFirst("%screenSaverName%", screenSaverName);
114 	textView->Insert(aboutScreenSaver);
115 
116 	textView->SetStylable(true);
117 	textView->SetFontAndColor(0, screenSaverName.Length(), be_bold_font);
118 //	textView->SetFontAndColor(25, 255, be_plain_font);
119 
120 	textView->MakeEditable(false);
121 
122 	view->AddChild(textView);
123 
124 	// make sure we receive messages from the views we added
125 	if (BWindow* window = view->Window())
126 		window->AddHandler(this);
127 
128 	fAdditiveCB->SetTarget(this);
129 	fSpeedS->SetTarget(this);
130 }
131 
132 // StartSaver
133 status_t
134 IFSSaver::StartSaver(BView *v, bool preview)
135 {
136 	display_mode mode;
137 	BScreen screen(B_MAIN_SCREEN_ID);
138 	screen.GetMode(&mode);
139 	float totalSize = mode.timing.h_total * mode.timing.v_total;
140 	float fps = mode.timing.pixel_clock * 1000.0 / totalSize;
141 
142 //printf("ticks per frame: %lldµs\n", (int64)floor(1000000.0 / fps + 0.5));
143 	SetTickSize((int64)floor(1000000.0 / fps + 0.5));
144 
145 	fIsPreview = preview;
146 	fBounds = v->Bounds();
147 
148 	_Init(fBounds);
149 	fIFS->SetAdditive(fIsPreview || fAdditive);
150 	fIFS->SetSpeed(fSpeed);
151 
152 	return B_OK;
153 }
154 
155 // StopSaver
156 void
157 IFSSaver::StopSaver()
158 {
159 	_Cleanup();
160 }
161 
162 // DirectConnected
163 void
164 IFSSaver::DirectConnected(direct_buffer_info* info)
165 {
166 //printf("IFSSaver::DirectConnected()\n");
167 	int32 request = info->buffer_state & B_DIRECT_MODE_MASK;
168 	switch (request) {
169 		case B_DIRECT_START:
170 //printf("B_DIRECT_START\n");
171 //printf("  bits_per_pixel: %ld\n", info->bits_per_pixel);
172 //printf("   bytes_per_row: %ld\n", info->bytes_per_row);
173 //printf("    pixel_format: %d\n", info->pixel_format);
174 //printf("   window_bounds: (%ld, %ld, %ld, %ld)\n",
175 //	info->window_bounds.left, info->window_bounds.top,
176 //	info->window_bounds.right, info->window_bounds.bottom);
177 			fDirectInfo.bits = info->bits;
178 			fDirectInfo.bytesPerRow = info->bytes_per_row;
179 			fDirectInfo.bits_per_pixel = info->bits_per_pixel;
180 			fDirectInfo.format = info->pixel_format;
181 			fDirectInfo.bounds = info->window_bounds;
182 			break;
183 		case B_DIRECT_STOP:
184 			fDirectInfo.bits = NULL;
185 			break;
186 		default:
187 			break;
188 	}
189 //printf("bits: %p\n", fDirectInfo.bits);
190 }
191 
192 // Draw
193 void
194 IFSSaver::Draw(BView *view, int32 frame)
195 {
196 //printf("IFSSaver::Draw(%ld) (%ldx%ld)\n", frame, view->Bounds().IntegerWidth() + 1, view->Bounds().IntegerHeight() + 1);
197 	if (frame == 0) {
198 		fLastDrawnFrame = -1;
199 		view->SetHighColor(0, 0, 0);
200 		view->FillRect(view->Bounds());
201 	}
202 	int32 frames = frame - fLastDrawnFrame;
203 	if ((fIsPreview || fDirectInfo.bits == NULL) && fLocker.Lock()) {
204 		fIFS->Draw(view, NULL, frames);
205 
206 		fLastDrawnFrame = frame;
207 		fLocker.Unlock();
208 	}
209 }
210 
211 // DirectDraw
212 void
213 IFSSaver::DirectDraw(int32 frame)
214 {
215 //bigtime_t now = system_time();
216 //printf("IFSSaver::DirectDraw(%ld)\n", frame);
217 	if (frame == 0)
218 		fLastDrawnFrame = -1;
219 	int32 frames = frame - fLastDrawnFrame;
220 	if (fDirectInfo.bits) {
221 		fIFS->Draw(NULL, &fDirectInfo, frames);
222 //printf("DirectDraw(): %lldµs\n", system_time() - now);
223 		fLastDrawnFrame = frame;
224 	}
225 }
226 
227 // SaveState
228 status_t
229 IFSSaver::SaveState(BMessage* into) const
230 {
231 	status_t ret = B_BAD_VALUE;
232 	if (into) {
233 		ret = into->AddBool("IFS additive", fAdditive);
234 		if (ret >= B_OK)
235 			ret = into->AddInt32("IFS speed", fSpeed);
236 	}
237 	return ret;
238 }
239 
240 // MessageReceived
241 void
242 IFSSaver::MessageReceived(BMessage* message)
243 {
244 	switch (message->what) {
245 		case MSG_TOGGLE_ADDITIVE:
246 			if (fLocker.Lock() && fIFS) {
247 				fAdditive = fAdditiveCB->Value() == B_CONTROL_ON;
248 				fIFS->SetAdditive(fAdditive || fIsPreview);
249 				fLocker.Unlock();
250 			}
251 			break;
252 		case MSG_SET_SPEED:
253 			if (fLocker.Lock() && fIFS) {
254 				fSpeed = fSpeedS->Value();
255 				fIFS->SetSpeed(fSpeed);
256 				fLocker.Unlock();
257 			}
258 			break;
259 		default:
260 			BHandler::MessageReceived(message);
261 	}
262 }
263 
264 // _Init
265 void
266 IFSSaver::_Init(BRect bounds)
267 {
268 	if (fLocker.Lock()) {
269 		delete fIFS;
270 		fIFS = new IFS(bounds);
271 		fLocker.Unlock();
272 	}
273 }
274 
275 // _Cleanup
276 void
277 IFSSaver::_Cleanup()
278 {
279 	if (fLocker.Lock()) {
280 		delete fIFS;
281 		fIFS = NULL;
282 		fLocker.Unlock();
283 	}
284 }
285 
286