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 { 40 prefs = new Prefs(); 41 42 int mini = false, deskbar = false, normal = false; 43 uint32 framecolor = 0, activecolor = 0, idlecolor = 0; 44 45 while (1) { 46 int option_index = 0; 47 static struct option long_options[] = { 48 {"deskbar", 0, &deskbar, true}, 49 {"width", 1, 0, 'w'}, 50 {"framecolor", 1, 0, 0}, 51 {"activecolor", 1, 0, 0}, 52 {"idlecolor", 1, 0, 0}, 53 {"mini", 0, &mini, true}, 54 {"normal", 0, &normal, true}, 55 {"help", 0, 0, 'h'}, 56 {0,0,0,0} 57 }; 58 int c = getopt_long(argc, argv, "hw:", long_options, &option_index); 59 if (c == -1) 60 break; 61 62 switch (c) { 63 case 0: 64 switch (option_index) { 65 case 2: /* framecolor */ 66 case 3: /* activecolor */ 67 case 4: /* idlecolor */ 68 uint32 rgb = strtoul(optarg, NULL, 0); 69 rgb = rgb << 8; 70 rgb |= 0x000000ff; 71 72 switch (option_index) { 73 case 2: 74 framecolor = rgb; 75 break; 76 case 3: 77 activecolor = rgb; 78 break; 79 case 4: 80 idlecolor = rgb; 81 break; 82 } 83 break; 84 } 85 break; 86 case 'w': 87 prefs->deskbar_icon_width = atoi(optarg); 88 if (prefs->deskbar_icon_width < GetMinimumViewWidth()) 89 prefs->deskbar_icon_width = GetMinimumViewWidth(); 90 else if (prefs->deskbar_icon_width > 50) prefs->deskbar_icon_width = 50; 91 break; 92 case 'h': 93 case '?': 94 Usage(); 95 break; 96 default: 97 printf("?? getopt returned character code 0%o ??\n", c); 98 break; 99 } 100 } 101 102 if (deskbar) { 103 prefs->window_mode = DESKBAR_MODE; 104 if (activecolor != 0) 105 prefs->deskbar_active_color = activecolor; 106 if (idlecolor != 0) 107 prefs->deskbar_idle_color = idlecolor; 108 if (framecolor != 0) 109 prefs->deskbar_frame_color = framecolor; 110 } else if (mini) { 111 prefs->window_mode = MINI_WINDOW_MODE; 112 if (activecolor != 0) 113 prefs->mini_active_color = activecolor; 114 if (idlecolor != 0) 115 prefs->mini_idle_color = idlecolor; 116 if (framecolor != 0) 117 prefs->mini_frame_color = framecolor; 118 } else if (normal) 119 prefs->window_mode = NORMAL_WINDOW_MODE; 120 121 prefs->Save(); 122 BuildPulse(); 123 } 124 125 126 void 127 PulseApp::BuildPulse() 128 { 129 // Remove this case for Deskbar add on API 130 131 // If loading the replicant fails, launch the app instead 132 // This allows having the replicant and the app open simultaneously 133 if (prefs->window_mode == DESKBAR_MODE && LoadInDeskbar()) { 134 PostMessage(new BMessage(B_QUIT_REQUESTED)); 135 return; 136 } else if (prefs->window_mode == DESKBAR_MODE) 137 prefs->window_mode = NORMAL_WINDOW_MODE; 138 139 PulseWindow *pulseWindow = NULL; 140 141 if (prefs->window_mode == MINI_WINDOW_MODE) 142 pulseWindow = new PulseWindow(prefs->mini_window_rect); 143 else 144 pulseWindow = new PulseWindow(prefs->normal_window_rect); 145 146 pulseWindow->MoveOnScreen(B_MOVE_IF_PARTIALLY_OFFSCREEN); 147 pulseWindow->Show(); 148 } 149 150 151 PulseApp::~PulseApp() 152 { 153 // Load the replicant after we save our preferences so they don't 154 // get overwritten by DeskbarPulseView's instance 155 prefs->Save(); 156 if (prefs->window_mode == DESKBAR_MODE) 157 LoadInDeskbar(); 158 159 delete prefs; 160 } 161 162 163 void 164 PulseApp::AboutRequested() 165 { 166 PulseApp::ShowAbout(true); 167 } 168 169 170 void 171 PulseApp::ShowAbout(bool asApplication) 172 { 173 // static version to be used in replicant mode 174 BString name; 175 if (asApplication) 176 name = B_TRANSLATE_SYSTEM_NAME("Pulse"); 177 else 178 name = B_TRANSLATE("Pulse"); 179 180 BString message = B_TRANSLATE( 181 "%s\n\nBy David Ramsey and Arve Hjønnevåg\n" 182 "Revised by Daniel Switkin\n"); 183 message.ReplaceFirst("%s", name); 184 BAlert *alert = new BAlert(B_TRANSLATE("Info"), 185 message.String(), B_TRANSLATE("OK")); 186 187 BTextView* view = alert->TextView(); 188 BFont font; 189 190 view->SetStylable(true); 191 view->GetFont(&font); 192 193 font.SetSize(18); 194 font.SetFace(B_BOLD_FACE); 195 view->SetFontAndColor(0, name.Length(), &font); 196 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 197 // Use the asynchronous version so we don't block the window's thread 198 alert->Go(NULL); 199 } 200 201 // #pragma mark - 202 203 204 /** Make sure we don't disable the last CPU - this is needed by 205 * descendants of PulseView for the popup menu and for CPUButton 206 * both as a replicant and not. 207 */ 208 209 bool 210 LastEnabledCPU(unsigned int my_cpu) 211 { 212 system_info sys_info; 213 get_system_info(&sys_info); 214 if (sys_info.cpu_count == 1) 215 return true; 216 217 for (unsigned int x = 0; x < sys_info.cpu_count; x++) { 218 if (x == my_cpu) 219 continue; 220 if (_kern_cpu_enabled(x) == 1) 221 return false; 222 } 223 return true; 224 } 225 226 227 /** Ensure that the mini mode and deskbar mode always show an indicator 228 * for each CPU, at least one pixel wide. 229 */ 230 231 int 232 GetMinimumViewWidth() 233 { 234 system_info sys_info; 235 get_system_info(&sys_info); 236 return (sys_info.cpu_count * 2) + 1; 237 } 238 239 240 void 241 Usage() 242 { 243 printf(B_TRANSLATE("Usage: Pulse [--mini] [-w width] [--width=width]\n" 244 "\t[--deskbar] [--normal] [--framecolor 0xrrggbb]\n" 245 "\t[--activecolor 0xrrggbb] [--idlecolor 0xrrggbb]\n")); 246 exit(0); 247 } 248 249 250 bool 251 LoadInDeskbar() 252 { 253 PulseApp *pulseapp = (PulseApp *)be_app; 254 BDeskbar *deskbar = new BDeskbar(); 255 // Don't allow two copies in the Deskbar at once 256 if (deskbar->HasItem("DeskbarPulseView")) { 257 delete deskbar; 258 return false; 259 } 260 261 // Must be 16 pixels high, the width is retrieved from the Prefs class 262 int width = pulseapp->prefs->deskbar_icon_width; 263 int min_width = GetMinimumViewWidth(); 264 if (width < min_width) { 265 pulseapp->prefs->deskbar_icon_width = min_width; 266 width = min_width; 267 } 268 269 BRect rect(0, 0, width - 1, 15); 270 DeskbarPulseView *replicant = new DeskbarPulseView(rect); 271 status_t err = deskbar->AddItem(replicant); 272 delete replicant; 273 delete deskbar; 274 if (err != B_OK) { 275 BString message; 276 snprintf(message.LockBuffer(512), 512, 277 B_TRANSLATE("Installing in Deskbar failed\n%s"), strerror(err)); 278 message.UnlockBuffer(); 279 BAlert *alert = new BAlert(B_TRANSLATE("Error"), 280 message.String(), B_TRANSLATE("OK")); 281 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 282 alert->Go(NULL); 283 return false; 284 } 285 286 return true; 287 } 288 289 290 int 291 main(int argc, char **argv) 292 { 293 PulseApp *pulseapp = new PulseApp(argc, argv); 294 pulseapp->Run(); 295 delete pulseapp; 296 return 0; 297 } 298