2 * Copyright 2003-2013 Haiku, Inc. All rights reserved
3 * Distributed under the terms of the MIT License.
6 * Axel Dörfler, axeld@pinc-software.de
7 * Jérôme Duval, jerome.duval@free.fr
9 * John Scipione, jscipione@gmail.com
13 #include "ScreenSaverRunner.h"
17 #include <DirectWindow.h>
18 #include <FindDirectory.h>
23 ScreenSaverRunner::ScreenSaverRunner(BWindow
* window
, BView
* view
,
24 ScreenSaverSettings
& settings
)
28 fIsDirectDraw(dynamic_cast<BDirectWindow
*>(window
) != NULL
),
39 ScreenSaverRunner::~ScreenSaverRunner()
49 ScreenSaverRunner::Run()
51 fThread
= spawn_thread(&_ThreadFunc
, "ScreenSaverRenderer", B_LOW_PRIORITY
,
55 return fThread
>= B_OK
? B_OK
: fThread
;
60 ScreenSaverRunner::Quit()
67 wait_for_thread(fThread
, &returnValue
);
73 ScreenSaverRunner::Suspend()
75 return suspend_thread(fThread
);
80 ScreenSaverRunner::Resume()
82 return resume_thread(fThread
);
87 ScreenSaverRunner::_LoadAddOn()
89 // This is a new set of preferences. Free up what we did have
90 // TODO: this is currently not meant to be used after creation
91 if (fThread
>= B_OK
) {
98 const char* moduleName
= fSettings
.ModuleName();
99 if (moduleName
== NULL
|| *moduleName
== '\0') {
104 BScreenSaver
* (*instantiate
)(BMessage
*, image_id
);
106 // try each directory until one succeeds
108 directory_which which
[] = {
109 B_USER_NONPACKAGED_ADDONS_DIRECTORY
,
110 B_USER_ADDONS_DIRECTORY
,
111 B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY
,
112 B_SYSTEM_ADDONS_DIRECTORY
,
116 for (uint32 i
= 0; i
< sizeof(which
) / sizeof(which
[0]); i
++) {
117 if (find_directory(which
[i
], &path
, false) != B_OK
)
119 else if (path
.Append("Screen Savers") != B_OK
)
121 else if (path
.Append(fSettings
.ModuleName()) != B_OK
)
124 fAddonImage
= load_add_on(path
.Path());
129 if (fAddonImage
> 0) {
130 // look for the one C function that should exist,
131 // instantiate_screen_saver()
132 if (get_image_symbol(fAddonImage
, "instantiate_screen_saver",
133 B_SYMBOL_TYPE_TEXT
, (void **)&instantiate
) != B_OK
) {
134 fprintf(stderr
, "Unable to find the instantiation function.\n");
137 fSettings
.GetModuleState(moduleName
, &state
);
138 fSaver
= instantiate(&state
, fAddonImage
);
141 if (fSaver
== NULL
) {
142 fprintf(stderr
, "Screen saver initialization failed.\n");
144 } else if (fSaver
->InitCheck() != B_OK
) {
145 fprintf(stderr
, "Screen saver initialization failed: %s.\n",
146 strerror(fSaver
->InitCheck()));
150 fprintf(stderr
, "Unable to open add-on %s.\n", path
.Path());
157 ScreenSaverRunner::_CleanUp()
162 if (fAddonImage
>= 0) {
163 status_t result
= unload_add_on(fAddonImage
);
164 if (result
!= B_OK
) {
165 fprintf(stderr
, "Unable to unload screen saver add-on: %s.\n",
174 ScreenSaverRunner::_Run()
176 static const uint32 kInitialTickRate
= 50000;
178 // TODO: This code is getting awfully complicated and should
179 // probably be refactored.
180 uint32 tickBase
= kInitialTickRate
;
181 int32 snoozeCount
= 0;
183 bigtime_t lastTickTime
= 0;
184 bigtime_t tick
= fSaver
!= NULL
? fSaver
->TickSize() : tickBase
;
187 // break the idle time up into ticks so that we can evaluate
188 // the quit condition with greater responsiveness
189 // otherwise a screen saver that sets, say, a 30 second tick
190 // will result in the screen saver not responding to deactivation
191 // for that length of time
193 if (system_time() - lastTickTime
< tick
)
196 // re-evaluate the tick time after each successful wakeup
197 // screensavers can adjust it on the fly, and we must be
198 // prepared to accomodate that
199 tick
= fSaver
!= NULL
? fSaver
->TickSize() : tickBase
;
201 if (tick
< tickBase
) {
205 } else if (tickBase
< kInitialTickRate
206 && tick
>= kInitialTickRate
) {
207 tickBase
= kInitialTickRate
;
210 lastTickTime
= system_time();
214 // if we are sleeping, do nothing
216 } else if (fSaver
!= NULL
) {
217 if (fSaver
->LoopOnCount() && frame
>= fSaver
->LoopOnCount()) {
220 snoozeCount
= fSaver
->LoopOffCount();
221 } else if (fWindow
->LockWithTimeout(5000LL) == B_OK
) {
223 // NOTE: BeOS R5 really calls DirectDraw()
224 // and then Draw() for the same frame
226 fSaver
->DirectDraw(frame
);
227 fSaver
->Draw(fView
, frame
);
245 ScreenSaverRunner::_ThreadFunc(void* data
)
247 ScreenSaverRunner
* runner
= (ScreenSaverRunner
*)data
;
248 return runner
->_Run();