xref: /haiku/src/apps/pulse/PulseApp.cpp (revision 1294543de9ac0eff000eaea1b18368c36435d08e)
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 <Locale.h>
25 #include <Rect.h>
26 
27 #include <syscalls.h>
28 
29 #include "Common.h"
30 #include "PulseWindow.h"
31 #include "DeskbarPulseView.h"
32 
33 #undef B_TRANSLATE_CONTEXT
34 #define B_TRANSLATE_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();
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 //	#pragma mark -
164 
165 
166 /** Make sure we don't disable the last CPU - this is needed by
167  *	descendants of PulseView for the popup menu and for CPUButton
168  *	both as a replicant and not.
169  */
170 
171 bool
172 LastEnabledCPU(int my_cpu)
173 {
174 	system_info sys_info;
175 	get_system_info(&sys_info);
176 	if (sys_info.cpu_count == 1)
177 		return true;
178 
179 	for (int x = 0; x < sys_info.cpu_count; x++) {
180 		if (x == my_cpu)
181 			continue;
182 		if (_kern_cpu_enabled(x) == 1)
183 			return false;
184 	}
185 	return true;
186 }
187 
188 
189 /**	Ensure that the mini mode and deskbar mode always show an indicator
190  *	for each CPU, at least one pixel wide.
191  */
192 
193 int
194 GetMinimumViewWidth()
195 {
196 	system_info sys_info;
197 	get_system_info(&sys_info);
198 	return (sys_info.cpu_count * 2) + 1;
199 }
200 
201 
202 void
203 Usage()
204 {
205 	printf(B_TRANSLATE("Usage: Pulse [--mini] [-w width] [--width=width]\n"
206 	       "\t[--deskbar] [--normal] [--framecolor 0xrrggbb]\n"
207 	       "\t[--activecolor 0xrrggbb] [--idlecolor 0xrrggbb]\n"));
208 	exit(0);
209 }
210 
211 
212 bool
213 LoadInDeskbar()
214 {
215 	PulseApp *pulseapp = (PulseApp *)be_app;
216 	BDeskbar *deskbar = new BDeskbar();
217 	// Don't allow two copies in the Deskbar at once
218 	if (deskbar->HasItem("DeskbarPulseView")) {
219 		delete deskbar;
220 		return false;
221 	}
222 
223 	// Must be 16 pixels high, the width is retrieved from the Prefs class
224 	int width = pulseapp->prefs->deskbar_icon_width;
225 	int min_width = GetMinimumViewWidth();
226 	if (width < min_width) {
227 		pulseapp->prefs->deskbar_icon_width = min_width;
228 		width = min_width;
229 	}
230 
231 	BRect rect(0, 0, width - 1, 15);
232 	DeskbarPulseView *replicant = new DeskbarPulseView(rect);
233 	status_t err = deskbar->AddItem(replicant);
234 	delete replicant;
235 	delete deskbar;
236 	if (err != B_OK) {
237 		BAlert *alert = new BAlert(NULL, strerror(err), B_TRANSLATE("OK"));
238 		alert->Go(NULL);
239 		return false;
240 	}
241 
242 	return true;
243 }
244 
245 
246 int
247 main(int argc, char **argv)
248 {
249 	PulseApp *pulseapp = new PulseApp(argc, argv);
250 	pulseapp->Run();
251 	delete pulseapp;
252 	return 0;
253 }
254