1 /*
2 * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
3 * This file may be used under the terms of the MIT License.
4 */
5
6
7 #include "ScreenConfigurations.h"
8
9 #include <new>
10 #include <string.h>
11 #include <strings.h>
12
13 #include <Message.h>
14
15
ScreenConfigurations()16 ScreenConfigurations::ScreenConfigurations()
17 :
18 fConfigurations(10, true)
19 {
20 }
21
22
~ScreenConfigurations()23 ScreenConfigurations::~ScreenConfigurations()
24 {
25 }
26
27
28 screen_configuration*
CurrentByID(int32 id) const29 ScreenConfigurations::CurrentByID(int32 id) const
30 {
31 for (int32 i = fConfigurations.CountItems(); i-- > 0;) {
32 screen_configuration* configuration = fConfigurations.ItemAt(i);
33
34 if (configuration->id == id && configuration->is_current)
35 return configuration;
36 }
37
38 return NULL;
39 }
40
41
42 screen_configuration*
BestFit(int32 id,const monitor_info * info,bool * _exactMatch) const43 ScreenConfigurations::BestFit(int32 id, const monitor_info* info,
44 bool* _exactMatch) const
45 {
46 if (info == NULL) {
47 // Only look for a matching ID - this is all we have
48 for (uint32 pass = 0; pass < 2; pass++) {
49 for (int32 i = fConfigurations.CountItems(); i-- > 0;) {
50 screen_configuration* configuration = fConfigurations.ItemAt(i);
51
52 if ((pass != 0 || !configuration->has_info)
53 && id == configuration->id)
54 return configuration;
55 }
56 }
57
58 return NULL;
59 }
60
61 // Look for a configuration that matches the monitor
62
63 bool exactMatch = false;
64 int32 bestScore = 0;
65 int32 bestIndex = -1;
66 BMessage stored;
67
68 for (int32 i = fConfigurations.CountItems(); i-- > 0;) {
69 screen_configuration* configuration = fConfigurations.ItemAt(i);
70 if (!configuration->has_info)
71 continue;
72
73 int32 score = 0;
74
75 if (!strcasecmp(configuration->info.vendor, info->vendor)
76 && !strcasecmp(configuration->info.name, info->name)
77 && configuration->info.product_id == info->product_id) {
78 score += 2;
79 if (strcmp(configuration->info.serial_number,
80 info->serial_number) == 0) {
81 exactMatch = true;
82 score += 2;
83 }
84 if (configuration->info.produced.year == info->produced.year
85 && configuration->info.produced.week == info->produced.week)
86 score++;
87 }
88
89 if (score > bestScore) {
90 bestScore = score;
91 bestIndex = i;
92 }
93 }
94
95 if (bestIndex < 0)
96 return NULL;
97
98 if (_exactMatch != NULL)
99 *_exactMatch = exactMatch;
100
101 return fConfigurations.ItemAt(bestIndex);
102 }
103
104
105 status_t
Set(int32 id,const monitor_info * info,const BRect & frame,const display_mode & mode)106 ScreenConfigurations::Set(int32 id, const monitor_info* info,
107 const BRect& frame, const display_mode& mode)
108 {
109 // Find configuration that we can overwrite
110
111 bool exactMatch;
112 screen_configuration* configuration = BestFit(id, info, &exactMatch);
113
114 if (configuration != NULL && configuration->has_info && !exactMatch) {
115 // only overwrite exact or unspecified configurations
116 configuration->is_current = false;
117 // TODO: provide a more obvious current mechanism...
118 configuration = NULL;
119 }
120
121 if (configuration == NULL) {
122 // we need a new configuration to store
123 configuration = new (std::nothrow) screen_configuration;
124 if (configuration == NULL)
125 return B_NO_MEMORY;
126
127 fConfigurations.AddItem(configuration);
128 }
129
130 configuration->id = id;
131 configuration->frame = frame;
132 configuration->is_current = true;
133
134 if (info != NULL) {
135 memcpy(&configuration->info, info, sizeof(monitor_info));
136 configuration->has_info = true;
137 } else
138 configuration->has_info = false;
139
140 memcpy(&configuration->mode, &mode, sizeof(display_mode));
141
142 return B_OK;
143 }
144
145
146 void
SetBrightness(int32 id,float brightness)147 ScreenConfigurations::SetBrightness(int32 id, float brightness)
148 {
149 for (int32 i = fConfigurations.CountItems(); i-- > 0;) {
150 screen_configuration* configuration = fConfigurations.ItemAt(i);
151 configuration->brightness = brightness;
152 }
153 }
154
155
156 float
Brightness(int32 id)157 ScreenConfigurations::Brightness(int32 id)
158 {
159 screen_configuration* configuration = fConfigurations.ItemAt(0);
160
161 if (configuration == NULL)
162 return -1;
163
164 return configuration->brightness;
165 }
166
167
168 void
Remove(screen_configuration * configuration)169 ScreenConfigurations::Remove(screen_configuration* configuration)
170 {
171 if (configuration == NULL)
172 return;
173
174 fConfigurations.RemoveItem(configuration);
175 // this also deletes the configuration
176 }
177
178
179 /*! Stores all configurations as separate BMessages into the provided
180 \a settings container.
181 */
182 status_t
Store(BMessage & settings) const183 ScreenConfigurations::Store(BMessage& settings) const
184 {
185 // Store the configuration of all current screens
186
187 for (int32 i = 0; i < fConfigurations.CountItems(); i++) {
188 screen_configuration* configuration = fConfigurations.ItemAt(i);
189
190 BMessage screenSettings;
191 screenSettings.AddInt32("id", configuration->id);
192
193 if (configuration->has_info) {
194 screenSettings.AddString("vendor", configuration->info.vendor);
195 screenSettings.AddString("name", configuration->info.name);
196 screenSettings.AddInt32("product id",
197 configuration->info.product_id);
198 screenSettings.AddString("serial",
199 configuration->info.serial_number);
200 screenSettings.AddInt32("produced week",
201 configuration->info.produced.week);
202 screenSettings.AddInt32("produced year",
203 configuration->info.produced.year);
204 }
205
206 screenSettings.AddRect("frame", configuration->frame);
207 screenSettings.AddData("mode", B_RAW_TYPE, &configuration->mode,
208 sizeof(display_mode));
209 screenSettings.AddFloat("brightness", configuration->brightness);
210
211 settings.AddMessage("screen", &screenSettings);
212 }
213
214 return B_OK;
215 }
216
217
218 status_t
Restore(const BMessage & settings)219 ScreenConfigurations::Restore(const BMessage& settings)
220 {
221 fConfigurations.MakeEmpty();
222
223 BMessage stored;
224 for (int32 i = 0; settings.FindMessage("screen", i, &stored) == B_OK; i++) {
225 const display_mode* mode;
226 ssize_t size;
227 int32 id;
228 if (stored.FindInt32("id", &id) != B_OK
229 || stored.FindData("mode", B_RAW_TYPE, (const void**)&mode,
230 &size) != B_OK
231 || size != sizeof(display_mode))
232 continue;
233
234 screen_configuration* configuration
235 = new(std::nothrow) screen_configuration;
236 if (configuration == NULL)
237 return B_NO_MEMORY;
238
239 configuration->id = id;
240 configuration->is_current = false;
241
242 const char* vendor;
243 const char* name;
244 uint32 productID;
245 const char* serial;
246 int32 week, year;
247 if (stored.FindString("vendor", &vendor) == B_OK
248 && stored.FindString("name", &name) == B_OK
249 && stored.FindInt32("product id", (int32*)&productID) == B_OK
250 && stored.FindString("serial", &serial) == B_OK
251 && stored.FindInt32("produced week", &week) == B_OK
252 && stored.FindInt32("produced year", &year) == B_OK) {
253 // create monitor info
254 strlcpy(configuration->info.vendor, vendor,
255 sizeof(configuration->info.vendor));
256 strlcpy(configuration->info.name, name,
257 sizeof(configuration->info.name));
258 strlcpy(configuration->info.serial_number, serial,
259 sizeof(configuration->info.serial_number));
260 configuration->info.product_id = productID;
261 configuration->info.produced.week = week;
262 configuration->info.produced.year = year;
263 configuration->has_info = true;
264 } else
265 configuration->has_info = false;
266
267 stored.FindRect("frame", &configuration->frame);
268 memcpy(&configuration->mode, mode, sizeof(display_mode));
269
270 if (stored.FindFloat("brightness", &configuration->brightness) != B_OK)
271 configuration->brightness = 1.0f;
272
273 fConfigurations.AddItem(configuration);
274 }
275
276 return B_OK;
277 }
278