xref: /haiku/src/apps/pulse/PulseApp.cpp (revision 0b2dbe7d46ee888392907c60131b7f7652314175)
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 #include "Common.h"
16 #include "PulseWindow.h"
17 #include "DeskbarPulseView.h"
18 
19 #include <Alert.h>
20 #include <Rect.h>
21 #include <Screen.h>
22 #include <Deskbar.h>
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <getopt.h>
28 
29 
30 PulseApp::PulseApp(int argc, char **argv)
31 	: BApplication(APP_SIGNATURE)
32 {
33 	prefs = new Prefs();
34 
35 	int mini = false, deskbar = false, normal = false;
36 	uint32 framecolor = 0, activecolor = 0, idlecolor = 0;
37 
38 	while (1) {
39 		int option_index = 0;
40 		static struct option long_options[] = {
41 			{"deskbar", 0, &deskbar, true},
42 			{"width", 1, 0, 'w'},
43 			{"framecolor", 1, 0, 0},
44 			{"activecolor", 1, 0, 0},
45 			{"idlecolor", 1, 0, 0},
46 			{"mini", 0, &mini, true},
47 			{"normal", 0, &normal, true},
48 			{"help", 0, 0, 'h'},
49 			{0,0,0,0}
50 		};
51 		int c = getopt_long(argc, argv, "hw:", long_options, &option_index);
52 		if (c == -1)
53 			break;
54 
55 		switch (c) {
56 			case 0:
57 				switch (option_index) {
58 					case 2: /* framecolor */
59 					case 3: /* activecolor */
60 					case 4: /* idlecolor */
61 						uint32 rgb = strtoul(optarg, NULL, 0);
62 						rgb = rgb << 8;
63 						rgb |= 0x000000ff;
64 
65 						switch (option_index) {
66 							case 2:
67 								framecolor = rgb;
68 								break;
69 							case 3:
70 								activecolor = rgb;
71 								break;
72 							case 4:
73 								idlecolor = rgb;
74 								break;
75 						}
76 						break;
77 				}
78 				break;
79 			case 'w':
80 				prefs->deskbar_icon_width = atoi(optarg);
81 				if (prefs->deskbar_icon_width < GetMinimumViewWidth())
82 					prefs->deskbar_icon_width = GetMinimumViewWidth();
83 				else if (prefs->deskbar_icon_width > 50) prefs->deskbar_icon_width = 50;
84 				break;
85 			case 'h':
86 			case '?':
87 				Usage();
88 				break;
89 			default:
90 				printf("?? getopt returned character code 0%o ??\n", c);
91 				break;
92 		}
93 	}
94 
95 	if (deskbar) {
96 		prefs->window_mode = DESKBAR_MODE;
97 		if (activecolor != 0)
98 			prefs->deskbar_active_color = activecolor;
99 		if (idlecolor != 0)
100 			prefs->deskbar_idle_color = idlecolor;
101 		if (framecolor != 0)
102 			prefs->deskbar_frame_color = framecolor;
103 	} else if (mini) {
104 		prefs->window_mode = MINI_WINDOW_MODE;
105 		if (activecolor != 0)
106 			prefs->mini_active_color = activecolor;
107 		if (idlecolor != 0)
108 			prefs->mini_idle_color = idlecolor;
109 		if (framecolor != 0)
110 			prefs->mini_frame_color = framecolor;
111 	} else if (normal)
112 		prefs->window_mode = NORMAL_WINDOW_MODE;
113 
114 	prefs->Save();
115 	BuildPulse();
116 }
117 
118 
119 void
120 PulseApp::BuildPulse()
121 {
122 	// Remove this case for Deskbar add on API
123 
124 	// If loading the replicant fails, launch the app instead
125 	// This allows having the replicant and the app open simultaneously
126 	if (prefs->window_mode == DESKBAR_MODE && LoadInDeskbar()) {
127 		PostMessage(new BMessage(B_QUIT_REQUESTED));
128 		return;
129 	} else
130 		prefs->window_mode = NORMAL_WINDOW_MODE;
131 
132 	PulseWindow *pulseWindow = NULL;
133 
134 	if (prefs->window_mode == MINI_WINDOW_MODE)
135 		pulseWindow = new PulseWindow(prefs->mini_window_rect);
136 	else
137 		pulseWindow = new PulseWindow(prefs->normal_window_rect);
138 
139 	// check if the window is on screen, and move it if not
140 	BRect frame = pulseWindow->Frame();
141 	BRect screenFrame = BScreen().Frame();
142 
143 	if (frame.left > screenFrame.right)
144 		pulseWindow->MoveBy(screenFrame.right - frame.right - 10, 0);
145 	else if (frame.right < 0)
146 		pulseWindow->MoveTo(10, frame.top);
147 
148 	if (frame.top > screenFrame.bottom)
149 		pulseWindow->MoveBy(0, screenFrame.bottom - frame.bottom - 10);
150 	else if (frame.bottom < 0)
151 		pulseWindow->MoveTo(frame.left, 10);
152 
153 	pulseWindow->Show();
154 }
155 
156 
157 PulseApp::~PulseApp()
158 {
159 	// Load the replicant after we save our preferences so they don't
160 	// get overwritten by DeskbarPulseView's instance
161 	prefs->Save();
162 	if (prefs->window_mode == DESKBAR_MODE)
163 		LoadInDeskbar();
164 
165 	delete prefs;
166 }
167 
168 
169 //	#pragma mark -
170 
171 
172 /** Make sure we don't disable the last CPU - this is needed by
173  *	descendants of PulseView for the popup menu and for CPUButton
174  *	both as a replicant and not.
175  */
176 
177 bool
178 LastEnabledCPU(int my_cpu)
179 {
180 	system_info sys_info;
181 	get_system_info(&sys_info);
182 	if (sys_info.cpu_count == 1)
183 		return true;
184 
185 	for (int x = 0; x < sys_info.cpu_count; x++) {
186 		if (x == my_cpu)
187 			continue;
188 		if (_kget_cpu_state_(x) == 1)
189 			return false;
190 	}
191 	return true;
192 }
193 
194 
195 /**	Ensure that the mini mode and deskbar mode always show an indicator
196  *	for each CPU, at least one pixel wide.
197  */
198 
199 int
200 GetMinimumViewWidth()
201 {
202 	system_info sys_info;
203 	get_system_info(&sys_info);
204 	return (sys_info.cpu_count * 2) + 1;
205 }
206 
207 
208 void
209 Usage()
210 {
211 	printf("Usage: Pulse [--mini] [-w width] [--width=width]\n"
212 	       "\t[--deskbar] [--normal] [--framecolor 0xrrggbb]\n"
213 	       "\t[--activecolor 0xrrggbb] [--idlecolor 0xrrggbb]\n");
214 	exit(0);
215 }
216 
217 
218 bool
219 LoadInDeskbar()
220 {
221 	PulseApp *pulseapp = (PulseApp *)be_app;
222 	BDeskbar *deskbar = new BDeskbar();
223 	// Don't allow two copies in the Deskbar at once
224 	if (deskbar->HasItem("DeskbarPulseView")) {
225 		delete deskbar;
226 		return false;
227 	}
228 
229 	// Must be 16 pixels high, the width is retrieved from the Prefs class
230 	int width = pulseapp->prefs->deskbar_icon_width;
231 	int min_width = GetMinimumViewWidth();
232 	if (width < min_width) {
233 		pulseapp->prefs->deskbar_icon_width = min_width;
234 		width = min_width;
235 	}
236 
237 	BRect rect(0, 0, width - 1, 15);
238 	DeskbarPulseView *replicant = new DeskbarPulseView(rect);
239 	status_t err = deskbar->AddItem(replicant);
240 	delete replicant;
241 	delete deskbar;
242 	if (err != B_OK) {
243 		BAlert *alert = new BAlert(NULL, strerror(err), "OK");
244 		alert->Go(NULL);
245 		return false;
246 	} else return true;
247 }
248 
249 
250 int
251 main(int argc, char **argv)
252 {
253 	PulseApp *pulseapp = new PulseApp(argc, argv);
254 	pulseapp->Run();
255 	delete pulseapp;
256 	return 0;
257 }
258