1 /* 2 * Copyright 2002-2005 Haiku 3 * Distributed under the terms of the MIT license. 4 * 5 * Updated by Sikosis (beos@gravity24hr.com) 6 * 7 * Copyright 1999, Be Incorporated. All Rights Reserved. 8 * This file may be used under the terms of the Be Sample Code License. 9 * 10 * Written by: Daniel Switkin 11 */ 12 13 14 #include "PulseApp.h" 15 16 #include <stdlib.h> 17 #include <stdio.h> 18 #include <string.h> 19 #include <getopt.h> 20 21 #include <Alert.h> 22 #include <Catalog.h> 23 #include <Deskbar.h> 24 #include <Rect.h> 25 #include <TextView.h> 26 27 #include <syscalls.h> 28 29 #include "Common.h" 30 #include "PulseWindow.h" 31 #include "DeskbarPulseView.h" 32 33 #undef B_TRANSLATION_CONTEXT 34 #define B_TRANSLATION_CONTEXT "PulseApp" 35 36 37 PulseApp::PulseApp(int argc, char **argv) 38 : BApplication(APP_SIGNATURE), 39 fPrefs(new Prefs()), 40 fRunFromReplicant(false), 41 fIsRunning(false), 42 fPrefsWindow(NULL) 43 { 44 int mini = false, deskbar = false, normal = false; 45 uint32 framecolor = 0, activecolor = 0, idlecolor = 0; 46 47 while (1) { 48 int option_index = 0; 49 static struct option long_options[] = { 50 {"deskbar", 0, &deskbar, true}, 51 {"width", 1, 0, 'w'}, 52 {"framecolor", 1, 0, 0}, 53 {"activecolor", 1, 0, 0}, 54 {"idlecolor", 1, 0, 0}, 55 {"mini", 0, &mini, true}, 56 {"normal", 0, &normal, true}, 57 {"help", 0, 0, 'h'}, 58 {0,0,0,0} 59 }; 60 int c = getopt_long(argc, argv, "hw:", long_options, &option_index); 61 if (c == -1) 62 break; 63 64 switch (c) { 65 case 0: 66 switch (option_index) { 67 case 2: /* framecolor */ 68 case 3: /* activecolor */ 69 case 4: /* idlecolor */ 70 uint32 rgb = strtoul(optarg, NULL, 0); 71 rgb = rgb << 8; 72 rgb |= 0x000000ff; 73 74 switch (option_index) { 75 case 2: 76 framecolor = rgb; 77 break; 78 case 3: 79 activecolor = rgb; 80 break; 81 case 4: 82 idlecolor = rgb; 83 break; 84 } 85 break; 86 } 87 break; 88 case 'w': 89 fPrefs->deskbar_icon_width = atoi(optarg); 90 if (fPrefs->deskbar_icon_width < GetMinimumViewWidth()) 91 fPrefs->deskbar_icon_width = GetMinimumViewWidth(); 92 else if (fPrefs->deskbar_icon_width > 50) fPrefs->deskbar_icon_width = 50; 93 break; 94 case 'h': 95 case '?': 96 Usage(); 97 break; 98 default: 99 printf("?? getopt returned character code 0%o ??\n", c); 100 break; 101 } 102 } 103 104 if (deskbar) { 105 fPrefs->window_mode = DESKBAR_MODE; 106 if (activecolor != 0) 107 fPrefs->deskbar_active_color = activecolor; 108 if (idlecolor != 0) 109 fPrefs->deskbar_idle_color = idlecolor; 110 if (framecolor != 0) 111 fPrefs->deskbar_frame_color = framecolor; 112 } else if (mini) { 113 fPrefs->window_mode = MINI_WINDOW_MODE; 114 if (activecolor != 0) 115 fPrefs->mini_active_color = activecolor; 116 if (idlecolor != 0) 117 fPrefs->mini_idle_color = idlecolor; 118 if (framecolor != 0) 119 fPrefs->mini_frame_color = framecolor; 120 } else if (normal) 121 fPrefs->window_mode = NORMAL_WINDOW_MODE; 122 123 fPrefs->Save(); 124 } 125 126 127 void 128 PulseApp::ReadyToRun() 129 { 130 if (!fRunFromReplicant) 131 BuildPulse(); 132 133 fIsRunning = true; 134 } 135 136 137 void 138 PulseApp::BuildPulse() 139 { 140 PulseWindow *pulseWindow = NULL; 141 142 if (fPrefs->window_mode == MINI_WINDOW_MODE) 143 pulseWindow = new PulseWindow(fPrefs->mini_window_rect); 144 else 145 pulseWindow = new PulseWindow(fPrefs->normal_window_rect); 146 147 pulseWindow->MoveOnScreen(B_MOVE_IF_PARTIALLY_OFFSCREEN); 148 pulseWindow->Show(); 149 } 150 151 152 PulseApp::~PulseApp() 153 { 154 fPrefs->Save(); 155 156 delete fPrefs; 157 } 158 159 160 void 161 PulseApp::MessageReceived(BMessage* message) 162 { 163 switch (message->what) { 164 case PV_PREFERENCES: 165 { 166 // This message can be posted before ReadyToRun from 167 // BRoster::Launch, in that case, take note to not show the main 168 // window but only the preferences 169 if (!fIsRunning) 170 fRunFromReplicant = true; 171 BMessenger from; 172 message->FindMessenger("settingsListener", &from); 173 174 175 if (fPrefsWindow != NULL) { 176 fPrefsWindow->Activate(true); 177 break; 178 } 179 // If the window is already open, bring it to the front 180 if (fPrefsWindow != NULL) { 181 fPrefsWindow->Activate(true); 182 break; 183 } 184 // Otherwise launch a new preferences window 185 PulseApp *pulseapp = (PulseApp *)be_app; 186 fPrefsWindow = new PrefsWindow(pulseapp->fPrefs->prefs_window_rect, 187 B_TRANSLATE("Pulse settings"), &from, 188 pulseapp->fPrefs); 189 if (fRunFromReplicant) { 190 fPrefsWindow->SetFlags(fPrefsWindow->Flags() 191 | B_QUIT_ON_WINDOW_CLOSE); 192 } 193 fPrefsWindow->Show(); 194 195 break; 196 } 197 198 case PV_ABOUT: 199 // This message can be posted before ReadyToRun from 200 // BRoster::Launch, in that case, take note to not show the main 201 // window but only the about box 202 if (!fIsRunning) 203 fRunFromReplicant = true; 204 PostMessage(B_ABOUT_REQUESTED); 205 break; 206 207 case PRV_QUIT: 208 fPrefsWindow = NULL; 209 fRunFromReplicant = false; 210 break; 211 212 default: 213 BApplication::MessageReceived(message); 214 break; 215 } 216 } 217 218 219 void 220 PulseApp::AboutRequested() 221 { 222 BString name = B_TRANSLATE("Pulse"); 223 224 BString message = B_TRANSLATE( 225 "%s\n\nBy David Ramsey and Arve Hjønnevåg\n" 226 "Revised by Daniel Switkin\n"); 227 message.ReplaceFirst("%s", name); 228 BAlert *alert = new BAlert(B_TRANSLATE("Info"), 229 message.String(), B_TRANSLATE("OK")); 230 231 if (fRunFromReplicant) 232 alert->SetFlags(alert->Flags() | B_QUIT_ON_WINDOW_CLOSE); 233 234 BTextView* view = alert->TextView(); 235 BFont font; 236 237 view->SetStylable(true); 238 view->GetFont(&font); 239 240 font.SetSize(18); 241 font.SetFace(B_BOLD_FACE); 242 view->SetFontAndColor(0, name.Length(), &font); 243 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 244 // Use the asynchronous version so we don't block the window's thread 245 alert->Go(NULL); 246 fRunFromReplicant = false; 247 } 248 249 // #pragma mark - 250 251 252 /** Make sure we don't disable the last CPU - this is needed by 253 * descendants of PulseView for the popup menu and for CPUButton 254 * both as a replicant and not. 255 */ 256 257 bool 258 LastEnabledCPU(unsigned int my_cpu) 259 { 260 system_info sys_info; 261 get_system_info(&sys_info); 262 if (sys_info.cpu_count == 1) 263 return true; 264 265 for (unsigned int x = 0; x < sys_info.cpu_count; x++) { 266 if (x == my_cpu) 267 continue; 268 if (_kern_cpu_enabled(x) == 1) 269 return false; 270 } 271 return true; 272 } 273 274 275 /** Ensure that the mini mode and deskbar mode always show an indicator 276 * for each CPU, at least one pixel wide. 277 */ 278 279 int 280 GetMinimumViewWidth() 281 { 282 system_info sys_info; 283 get_system_info(&sys_info); 284 return (sys_info.cpu_count * 2) + 1; 285 } 286 287 288 void 289 Usage() 290 { 291 puts(B_TRANSLATE("Usage: Pulse [--mini] [-w width] [--width=width]\n" 292 "\t[--deskbar] [--normal] [--framecolor 0xrrggbb]\n" 293 "\t[--activecolor 0xrrggbb] [--idlecolor 0xrrggbb]")); 294 exit(0); 295 } 296 297 298 bool 299 LoadInDeskbar() 300 { 301 PulseApp *pulseapp = (PulseApp *)be_app; 302 BDeskbar *deskbar = new BDeskbar(); 303 // Don't allow two copies in the Deskbar at once 304 if (deskbar->HasItem("DeskbarPulseView")) { 305 delete deskbar; 306 return false; 307 } 308 309 // Must be 16 pixels high, the width is retrieved from the Prefs class 310 int width = pulseapp->fPrefs->deskbar_icon_width; 311 int min_width = GetMinimumViewWidth(); 312 if (width < min_width) { 313 pulseapp->fPrefs->deskbar_icon_width = min_width; 314 width = min_width; 315 } 316 317 float height = deskbar->MaxItemHeight(); 318 BRect rect(0, 0, width - 1, height - 1); 319 DeskbarPulseView *replicant = new DeskbarPulseView(rect); 320 status_t err = deskbar->AddItem(replicant); 321 delete replicant; 322 delete deskbar; 323 if (err != B_OK) { 324 BString message; 325 snprintf(message.LockBuffer(512), 512, 326 B_TRANSLATE("Installing in Deskbar failed\n%s"), strerror(err)); 327 message.UnlockBuffer(); 328 BAlert *alert = new BAlert(B_TRANSLATE("Error"), 329 message.String(), B_TRANSLATE("OK")); 330 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 331 alert->Go(NULL); 332 return false; 333 } 334 335 return true; 336 } 337 338 339 int 340 main(int argc, char **argv) 341 { 342 PulseApp *pulseapp = new PulseApp(argc, argv); 343 pulseapp->Run(); 344 delete pulseapp; 345 return 0; 346 } 347