Bearsampp 2026.7.11
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 return;
88 }
89
90 Log::trace('Loading window created successfully - handle: ' . $this->wbWindow);
91
92 // CRITICAL: wb_set_visible() must be called AFTER window creation in PHP 8.4
93 // The WS_VISIBLE flag during creation doesn't work
94 Log::trace('Making window visible with wb_set_visible()');
95 wb_set_visible($this->wbWindow, true);
96 Log::trace('Window set to visible');
97
98 Log::trace('Drawing image...');
99 $bearsamppWinbinder->drawImage($this->wbWindow, Path::getImagesPath() . '/bearsampp.bmp');
100 Log::trace('Image drawn');
101
102 Log::trace('Creating progress bar...');
103 $this->wbProgressBar = $bearsamppWinbinder->createProgressBar($this->wbWindow, self::GAUGE + 1, 42, 24, self::WINDOW_WIDTH - 62, 15);
104 Log::trace('Progress bar created: ' . var_export($this->wbProgressBar, true));
105
106 Log::trace('Drawing initial text...');
107 $this->wbLabel = $bearsamppWinbinder->drawText($this->wbWindow, '', 42, 0, self::WINDOW_WIDTH - 64, 25);
108 Log::trace('Label created: ' . var_export($this->wbLabel, true));
109
110 // Set the handler and start the main loop
111 Log::trace('Setting window handler...');
112 $bearsamppWinbinder->setHandler($this->wbWindow, $this, 'processLoading', 10);
113 Log::trace('Handler set, starting main loop...');
114 $bearsamppWinbinder->mainLoop();
115 Log::trace('Main loop exited');
116 }
117
123 public function incrProgressBar($nb = 1)
124 {
125 global $bearsamppCore, $bearsamppWinbinder;
126
127 for ($i = 0; $i < $nb; $i++) {
128 $bearsamppWinbinder->incrProgressBar($this->wbProgressBar);
129 $bearsamppWinbinder->drawImage($this->wbWindow, Path::getImagesPath() . '/bearsampp.bmp', 4, 2, 32, 32);
130 }
131
132 $bearsamppWinbinder->wait();
133 $bearsamppWinbinder->wait($this->wbWindow);
134 }
135
145 public function processLoading($window, $id, $ctrl, $param1, $param2)
146 {
147 global $bearsamppRoot, $bearsamppWinbinder;
148
149 switch ($id) {
150 case IDCLOSE:
152 break;
153 }
154
155 // Set a maximum number of iterations to prevent infinite loops
156 $maxIterations = 10;
157 $iterations = 0;
158
159 // Set a timeout for the entire loading process
160 $startTime = microtime(true); // Use microtime for more precise timing
161 $maxLoadingTime = 15; // 15 seconds maximum
162
163 while ($iterations < $maxIterations && (microtime(true) - $startTime) < $maxLoadingTime) {
164 $bearsamppRoot->removeErrorHandling();
165 $bearsamppWinbinder->resetProgressBar($this->wbProgressBar);
166
167 usleep(100000);
168
169 for ($i = 0; $i < self::GAUGE && (microtime(true) - $startTime) < $maxLoadingTime; $i++) {
170 $this->incrProgressBar();
171
172 // Check for status file updates to show current service being processed
174
175 usleep(100000);
176 }
177
178 // Check if all services have started successfully
179 $allServicesStarted = $this->checkAllServicesStarted();
180 if ($allServicesStarted) {
181 Log::trace('All services started successfully');
182 break;
183 }
184
185 $iterations++;
186 Log::trace('Loading iteration ' . $iterations . ' completed, checking services again');
187 }
188
189 if ($iterations >= $maxIterations) {
190 Log::trace('Maximum iterations reached (' . $maxIterations . '), some services may not have started properly');
191 }
192
193 if ((microtime(true) - $startTime) >= $maxLoadingTime) {
194 Log::trace('Loading timeout reached (' . $maxLoadingTime . ' seconds), some services may not have started properly');
195 }
196
197 // Close the loading window
198 Log::trace('Closing loading window');
200 }
201
207 private function updateLoadingText($text)
208 {
209 global $bearsamppWinbinder;
210
211 if ($this->wbLabel) {
212 wb_set_text($this->wbLabel, $text);
213 wb_refresh($this->wbWindow);
214 }
215 }
216
221 private function updateLabelFromStatusFile()
222 {
223 global $bearsamppCore, $bearsamppWinbinder;
224
225 $statusFile = Path::getTmpPath() . '/loading_status.txt';
226
227 if (file_exists($statusFile)) {
228 $content = @file_get_contents($statusFile);
229 if ($content !== false && !empty($content)) {
230 $status = @json_decode($content, true);
231 if ($status && isset($status['text']) && !empty($status['text'])) {
232 // Clear the text area and redraw with new text
233 $bearsamppWinbinder->drawRect($this->wbWindow, 42, 0, self::WINDOW_WIDTH - 52, 25);
234 $this->wbLabel = $bearsamppWinbinder->drawText($this->wbWindow, $status['text'], 42, 0, self::WINDOW_WIDTH - 64, 25);
235 }
236 }
237 } else {
238 // If no status file exists, show a default message
239 $currentText = $this->wbLabel;
240 if (empty($currentText)) {
241 $bearsamppWinbinder->drawRect($this->wbWindow, 42, 0, self::WINDOW_WIDTH - 52, 25);
242 $this->wbLabel = $bearsamppWinbinder->drawText($this->wbWindow, 'Processing...', 42, 0, self::WINDOW_WIDTH - 64, 25);
243 }
244 }
245 }
246
254 private function checkAllServicesStarted()
255 {
256 global $bearsamppBins;
257
258 Log::trace('Checking if all services have started successfully');
259
260 // getServices() already filters to enabled-only services
261 $allStarted = true;
262 foreach ($bearsamppBins->getServices() as $sName => $service) {
263 $serviceName = $service->getName();
264 $this->updateLoadingText('Checking ' . $serviceName . '...');
265
266 try {
267 $state = Win32Native::getServiceState($serviceName);
268 $serviceRunning = ($state === 'Running');
269 Log::trace('Service ' . $sName . ' status check: ' . ($serviceRunning ? 'running' : 'not running') . ' (state: ' . var_export($state, true) . ')');
270 } catch (\Throwable $e) {
271 Log::trace('Exception during service status check for ' . $sName . ': ' . $e->getMessage());
272 $serviceRunning = false;
273 }
274
275 if (!$serviceRunning) {
276 Log::trace('Service ' . $sName . ' is not running');
277 $allStarted = false;
278 break;
279 }
280 }
281
282 Log::trace('All services started check result: ' . ($allStarted ? 'true' : 'false'));
283 return $allStarted;
284 }
285}
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