1 //**************************************************************************************** 2 // 3 // File: PulseView.cpp 4 // 5 // Written by: David Ramsey and Daniel Switkin 6 // 7 // Copyright 1999, Be Incorporated 8 // 9 //**************************************************************************************** 10 11 #include "PulseView.h" 12 13 #include <stdlib.h> 14 #include <stdio.h> 15 #include <string.h> 16 17 #include <Alert.h> 18 #include <Catalog.h> 19 20 #include <syscalls.h> 21 22 #include "Common.h" 23 #include "PulseApp.h" 24 25 #undef B_TRANSLATION_CONTEXT 26 #define B_TRANSLATION_CONTEXT "PulseView" 27 28 29 PulseView::PulseView(BRect rect, const char *name) 30 : 31 BView(rect, name, B_FOLLOW_ALL_SIDES, 32 B_WILL_DRAW | B_PULSE_NEEDED | B_FRAME_EVENTS), 33 kCPUCount(sysconf(_SC_NPROCESSORS_CONF)), 34 cpu_times(new double[kCPUCount]), 35 prev_active(new bigtime_t[kCPUCount]) 36 { 37 38 popupmenu = NULL; 39 cpu_menu_items = NULL; 40 41 // Don't init the menus for the DeskbarPulseView, because this instance 42 // will only be used to archive the replicant 43 if (strcmp(name, "DeskbarPulseView") != 0) { 44 Init(); 45 } 46 } 47 48 // This version will be used by the instantiated replicant 49 PulseView::PulseView(BMessage *message) 50 : 51 BView(message), 52 kCPUCount(sysconf(_SC_NPROCESSORS_CONF)), 53 cpu_times(new double[kCPUCount]), 54 prev_active(new bigtime_t[kCPUCount]) 55 { 56 SetResizingMode(B_FOLLOW_ALL_SIDES); 57 SetFlags(B_WILL_DRAW | B_PULSE_NEEDED); 58 59 popupmenu = NULL; 60 cpu_menu_items = NULL; 61 Init(); 62 } 63 64 void PulseView::Init() { 65 memset(cpu_times, 0, sizeof(double) * kCPUCount); 66 memset(prev_active, 0, sizeof(double) * kCPUCount); 67 68 popupmenu = new BPopUpMenu("PopUpMenu", false, false, B_ITEMS_IN_COLUMN); 69 popupmenu->SetFont(be_plain_font); 70 mode1 = new BMenuItem("", NULL, 0, 0); 71 mode2 = new BMenuItem("", NULL, 0, 0); 72 preferences = new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS), 73 new BMessage(PV_PREFERENCES), 0, 0); 74 about = new BMenuItem(B_TRANSLATE("About Pulse" B_UTF8_ELLIPSIS), 75 new BMessage(PV_ABOUT), 0, 0); 76 77 popupmenu->AddItem(mode1); 78 popupmenu->AddItem(mode2); 79 popupmenu->AddSeparatorItem(); 80 81 system_info sys_info; 82 get_system_info(&sys_info); 83 84 // Only add menu items to control CPUs on an SMP machine 85 if (sys_info.cpu_count >= 2) { 86 cpu_menu_items = new BMenuItem *[sys_info.cpu_count]; 87 char temp[20]; 88 for (unsigned int x = 0; x < sys_info.cpu_count; x++) { 89 sprintf(temp, "CPU %d", x + 1); 90 BMessage *message = new BMessage(PV_CPU_MENU_ITEM); 91 message->AddInt32("which", x); 92 cpu_menu_items[x] = new BMenuItem(temp, message, 0, 0); 93 popupmenu->AddItem(cpu_menu_items[x]); 94 } 95 popupmenu->AddSeparatorItem(); 96 } 97 98 popupmenu->AddItem(preferences); 99 popupmenu->AddItem(about); 100 } 101 102 void PulseView::MouseDown(BPoint point) { 103 BPoint cursor; 104 uint32 buttons; 105 MakeFocus(true); 106 GetMouse(&cursor, &buttons, true); 107 108 if (buttons & B_SECONDARY_MOUSE_BUTTON) { 109 ConvertToScreen(&point); 110 // Use the asynchronous version so we don't interfere with 111 // the window responding to Pulse() events 112 popupmenu->Go(point, true, false, true); 113 } 114 } 115 116 void PulseView::Update() { 117 system_info sys_info; 118 get_system_info(&sys_info); 119 bigtime_t now = system_time(); 120 121 cpu_info* cpuInfos = new cpu_info[sys_info.cpu_count]; 122 get_cpu_info(0, sys_info.cpu_count, cpuInfos); 123 124 // Calculate work done since last call to Update() for each CPU 125 for (unsigned int x = 0; x < sys_info.cpu_count; x++) { 126 double cpu_time = (double)(cpuInfos[x].active_time - prev_active[x]) 127 / (now - prev_time); 128 prev_active[x] = cpuInfos[x].active_time; 129 if (cpu_time < 0) cpu_time = 0; 130 if (cpu_time > 1) cpu_time = 1; 131 cpu_times[x] = cpu_time; 132 133 if (sys_info.cpu_count >= 2) { 134 if (!_kern_cpu_enabled(x) && cpu_menu_items[x]->IsMarked()) 135 cpu_menu_items[x]->SetMarked(false); 136 if (_kern_cpu_enabled(x) && !cpu_menu_items[x]->IsMarked()) 137 cpu_menu_items[x]->SetMarked(true); 138 } 139 } 140 prev_time = now; 141 142 delete[] cpuInfos; 143 } 144 145 void PulseView::ChangeCPUState(BMessage *message) { 146 int which = message->FindInt32("which"); 147 148 if (!LastEnabledCPU(which)) { 149 _kern_set_cpu_enabled(which, (int)!cpu_menu_items[which]->IsMarked()); 150 } else { 151 BAlert *alert = new BAlert(B_TRANSLATE("Info"), 152 B_TRANSLATE("You can't disable the last active CPU."), 153 B_TRANSLATE("OK")); 154 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 155 alert->Go(NULL); 156 } 157 } 158 159 PulseView::~PulseView() { 160 if (popupmenu != NULL) delete popupmenu; 161 if (cpu_menu_items != NULL) delete[] cpu_menu_items; 162 163 delete[] prev_active; 164 delete[] cpu_times; 165 } 166 167