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