xref: /haiku/src/apps/pulse/PulseView.cpp (revision 36bf86d2b6114bd2a21ca4edaf7b996921c5da44)
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 
PulseView(BRect rect,const char * name)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
PulseView(BMessage * message)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 
Init()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 
MouseDown(BPoint point)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 
Update()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 
ChangeCPUState(BMessage * message)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 
~PulseView()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