Bearsampp 2026.9.23
Loading...
Searching...
No Matches
class.action.loading.php
Go to the documentation of this file.
1<?php
2/*
3 *
4 * * Copyright (c) 2022-2025 Bearsampp
5 * * License: GNU General Public License version 3 or later; see LICENSE.txt
6 * * Website: https://bearsampp.com
7 * * Github: https://github.com/Bearsampp
8 *
9 */
10
17{
19 const WINDOW_WIDTH = 360;
20
22 const WINDOW_HEIGHT = 90;
23
25 const GAUGE = 20;
26
28 private $wbWindow;
29
31 private $wbLabel;
32
35
43 public function __construct($args)
44 {
45 global $bearsamppCore, $bearsamppLang, $bearsamppWinbinder;
46
47 $currentPid = Win32Ps::getCurrentPid();
48 Log::trace('ActionLoading constructor started - PID: ' . $currentPid);
49
50 $bearsamppWinbinder->reset();
51 Log::trace('WinBinder reset complete');
52
53 $bearsamppCore->addLoadingPid($currentPid);
54 Log::trace('Loading PID added to tracking file: ' . $currentPid);
55
56 // Check for already running loading processes
57 $pidFile = $bearsamppCore->getLoadingPid();
58 if (file_exists($pidFile)) {
59 $pids = file($pidFile);
60 foreach ($pids as $pid) {
61 $pid = trim($pid);
62 if (!empty($pid) && $pid != $currentPid) {
63 Log::trace('ActionLoading: Found another loading process (PID ' . $pid . '), killing it');
64 Win32Ps::kill($pid);
65 }
66 }
67 }
68
69 // Screen information
70 Log::trace('Getting screen information');
71 $screenArea = explode(' ', $bearsamppWinbinder->getSystemInfo(WinBinder::SYSINFO_WORKAREA));
72 $screenWidth = intval($screenArea[2]);
73 $screenHeight = intval($screenArea[3]);
74 $xPos = $screenWidth - self::WINDOW_WIDTH;
75 $yPos = $screenHeight - self::WINDOW_HEIGHT - 5;
76 Log::trace('Screen dimensions: ' . $screenWidth . 'x' . $screenHeight . ', Window position: (' . $xPos . ',' . $yPos . ')');
77
78 // Create the window and progress bar
79 Log::trace('Creating loading window...');
80 $this->wbWindow = $bearsamppWinbinder->createWindow(null, ToolDialog, null, $xPos, $yPos, self::WINDOW_WIDTH, self::WINDOW_HEIGHT, WBC_TOP, null);
81
82 // Check if window was created successfully
83 if ($this->wbWindow === false || $this->wbWindow === null) {
84 Log::error('CRITICAL: Failed to create loading window - window handle is: ' . var_export($this->wbWindow, true));
85 Log::error('WinBinder extension loaded: ' . (extension_loaded('winbinder') ? 'YES' : 'NO'));
86 Log::error('wb_create_window function exists: ' . (function_exists('wb_create_window') ? 'YES' : 'NO'));
87
88 return;
89 }
90
91 Log::trace('Loading window created successfully - handle: ' . $this->wbWindow);
92
93 // CRITICAL: wb_set_visible() must be called AFTER window creation in PHP 8.4
94 // The WS_VISIBLE flag during creation doesn't work
95 Log::trace('Making window visible with wb_set_visible()');
96 wb_set_visible($this->wbWindow, true);
97 Log::trace('Window set to visible');
98
99 Log::trace('Drawing image...');
100 $bearsamppWinbinder->drawImage($this->wbWindow, Path::getImagesPath() . '/bearsampp.bmp');
101 Log::trace('Image drawn');
102
103 Log::trace('Creating progress bar...');
104 $this->wbProgressBar = $bearsamppWinbinder->createProgressBar($this->wbWindow, self::GAUGE + 1, 42, 24, self::WINDOW_WIDTH - 62, 15);
105 Log::trace('Progress bar created: ' . var_export($this->wbProgressBar, true));
106
107 Log::trace('Drawing initial text...');
108 $this->wbLabel = $bearsamppWinbinder->drawText($this->wbWindow, '', 42, 0, self::WINDOW_WIDTH - 64, 25);
109 Log::trace('Label created: ' . var_export($this->wbLabel, true));
110
111 // Set the handler and start the main loop
112 Log::trace('Setting window handler...');
113 $bearsamppWinbinder->setHandler($this->wbWindow, $this, 'processLoading', 10);
114 Log::trace('Handler set, starting main loop...');
115 $bearsamppWinbinder->mainLoop();
116 Log::trace('Main loop exited');
117 }
118
124 public function incrProgressBar($nb = 1)
125 {
126 global $bearsamppCore, $bearsamppWinbinder;
127
128 for ($i = 0; $i < $nb; $i++) {
129 $bearsamppWinbinder->incrProgressBar($this->wbProgressBar);
130 $bearsamppWinbinder->drawImage($this->wbWindow, Path::getImagesPath() . '/bearsampp.bmp', 4, 2, 32, 32);
131 }
132
133 $bearsamppWinbinder->wait();
134 $bearsamppWinbinder->wait($this->wbWindow);
135 }
136
146 public function processLoading($window, $id, $ctrl, $param1, $param2)
147 {
148 global $bearsamppRoot, $bearsamppWinbinder;
149
150 switch ($id) {
151 case IDCLOSE:
153 break;
154 }
155
156 // Set a maximum number of iterations to prevent infinite loops
157 $maxIterations = 10;
158 $iterations = 0;
159
160 // Set a timeout for the entire loading process
161 $startTime = microtime(true); // Use microtime for more precise timing
162 $maxLoadingTime = 15; // 15 seconds maximum
163
164 while ($iterations < $maxIterations && (microtime(true) - $startTime) < $maxLoadingTime) {
165 $bearsamppRoot->removeErrorHandling();
166 $bearsamppWinbinder->resetProgressBar($this->wbProgressBar);
167
168 usleep(100000);
169
170 for ($i = 0; $i < self::GAUGE && (microtime(true) - $startTime) < $maxLoadingTime; $i++) {
171 $this->incrProgressBar();
172
173 // Check for status file updates to show current service being processed
175
176 usleep(100000);
177 }
178
179 // Check if all services have started successfully
180 $allServicesStarted = $this->checkAllServicesStarted();
181 if ($allServicesStarted) {
182 Log::trace('All services started successfully');
183 break;
184 }
185
186 $iterations++;
187 Log::trace('Loading iteration ' . $iterations . ' completed, checking services again');
188 }
189
190 if ($iterations >= $maxIterations) {
191 Log::trace('Maximum iterations reached (' . $maxIterations . '), some services may not have started properly');
192 }
193
194 if ((microtime(true) - $startTime) >= $maxLoadingTime) {
195 Log::trace('Loading timeout reached (' . $maxLoadingTime . ' seconds), some services may not have started properly');
196 }
197
198 // Close the loading window
199 Log::trace('Closing loading window');
201 }
202
208 private function updateLoadingText($text)
209 {
210 global $bearsamppWinbinder;
211
212 if ($this->wbLabel) {
213 wb_set_text($this->wbLabel, $text);
214 wb_refresh($this->wbWindow);
215 }
216 }
217
222 private function updateLabelFromStatusFile()
223 {
224 global $bearsamppCore, $bearsamppWinbinder;
225
226 $statusFile = Path::getTmpPath() . '/loading_status.txt';
227
228 if (file_exists($statusFile)) {
229 $content = @file_get_contents($statusFile);
230 if ($content !== false && !empty($content)) {
231 $status = @json_decode($content, true);
232 if ($status && isset($status['text']) && !empty($status['text'])) {
233 // Clear the text area and redraw with new text
234 $bearsamppWinbinder->drawRect($this->wbWindow, 42, 0, self::WINDOW_WIDTH - 52, 25);
235 $this->wbLabel = $bearsamppWinbinder->drawText($this->wbWindow, $status['text'], 42, 0, self::WINDOW_WIDTH - 64, 25);
236 }
237 }
238 } else {
239 // If no status file exists, show a default message
240 $currentText = $this->wbLabel;
241 if (empty($currentText)) {
242 $bearsamppWinbinder->drawRect($this->wbWindow, 42, 0, self::WINDOW_WIDTH - 52, 25);
243 $this->wbLabel = $bearsamppWinbinder->drawText($this->wbWindow, 'Processing...', 42, 0, self::WINDOW_WIDTH - 64, 25);
244 }
245 }
246 }
247
255 private function checkAllServicesStarted()
256 {
257 global $bearsamppBins;
258
259 Log::trace('Checking if all services have started successfully');
260
261 // getServices() already filters to enabled-only services
262 $allStarted = true;
263 foreach ($bearsamppBins->getServices() as $sName => $service) {
264 $serviceName = $service->getName();
265 $this->updateLoadingText('Checking ' . $serviceName . '...');
266
267 try {
268 $state = Win32Native::getServiceState($serviceName);
269 $serviceRunning = ($state === 'Running');
270 Log::trace('Service ' . $sName . ' status check: ' . ($serviceRunning ? 'running' : 'not running') . ' (state: ' . var_export($state, true) . ')');
271 } catch (\Throwable $e) {
272 Log::trace('Exception during service status check for ' . $sName . ': ' . $e->getMessage());
273 $serviceRunning = false;
274 }
275
276 if (!$serviceRunning) {
277 Log::trace('Service ' . $sName . ' is not running');
278 $allStarted = false;
279 break;
280 }
281 }
282
283 Log::trace('All services started check result: ' . ($allStarted ? 'true' : 'false'));
284
285 return $allStarted;
286 }
287}
global $bearsamppBins
global $bearsamppLang
global $bearsamppRoot
global $bearsamppCore
processLoading($window, $id, $ctrl, $param1, $param2)
static trace($data, $file=null)
static error($data, $file=null)
static getTmpPath($aetrayPath=false)
static getImagesPath($aetrayPath=false)
static getServiceState($serviceName)
static getCurrentPid()
static kill($pid)
const SYSINFO_WORKAREA