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 16 ScreenConfigurations::ScreenConfigurations() 17 : 18 fConfigurations(10, true) 19 { 20 } 21 22 23 ScreenConfigurations::~ScreenConfigurations() 24 { 25 } 26 27 28 screen_configuration* 29 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* 43 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 (info->serial_number[0] != '\0' 80 && !strcmp(configuration->info.serial_number, 81 info->serial_number)) { 82 exactMatch = true; 83 score += 2; 84 } 85 if (configuration->info.produced.year == info->produced.year 86 && configuration->info.produced.week == info->produced.week) 87 score++; 88 } 89 90 if (score > bestScore) { 91 bestScore = score; 92 bestIndex = i; 93 } 94 } 95 96 if (bestIndex < 0) 97 return NULL; 98 99 if (_exactMatch != NULL) 100 *_exactMatch = exactMatch; 101 102 return fConfigurations.ItemAt(bestIndex); 103 } 104 105 106 status_t 107 ScreenConfigurations::Set(int32 id, const monitor_info* info, 108 const BRect& frame, const display_mode& mode) 109 { 110 // Find configuration that we can overwrite 111 112 bool exactMatch; 113 screen_configuration* configuration = BestFit(id, info, &exactMatch); 114 115 if (configuration != NULL && configuration->has_info && !exactMatch) { 116 // only overwrite exact or unspecified configurations 117 configuration->is_current = false; 118 // TODO: provide a more obvious current mechanism... 119 configuration = NULL; 120 } 121 122 if (configuration == NULL) { 123 // we need a new configuration to store 124 configuration = new (std::nothrow) screen_configuration; 125 if (configuration == NULL) 126 return B_NO_MEMORY; 127 128 fConfigurations.AddItem(configuration); 129 } 130 131 configuration->id = id; 132 configuration->frame = frame; 133 configuration->is_current = true; 134 135 if (info != NULL) { 136 memcpy(&configuration->info, info, sizeof(monitor_info)); 137 configuration->has_info = true; 138 } else 139 configuration->has_info = false; 140 141 memcpy(&configuration->mode, &mode, sizeof(display_mode)); 142 143 return B_OK; 144 } 145 146 147 void 148 ScreenConfigurations::Remove(screen_configuration* configuration) 149 { 150 if (configuration == NULL) 151 return; 152 153 fConfigurations.RemoveItem(configuration); 154 // this also deletes the configuration 155 } 156 157 158 /*! Stores all configurations as separate BMessages into the provided 159 \a settings container. 160 */ 161 status_t 162 ScreenConfigurations::Store(BMessage& settings) const 163 { 164 // Store the configuration of all current screens 165 166 for (int32 i = 0; i < fConfigurations.CountItems(); i++) { 167 screen_configuration* configuration = fConfigurations.ItemAt(i); 168 169 BMessage screenSettings; 170 screenSettings.AddInt32("id", configuration->id); 171 172 if (configuration->has_info) { 173 screenSettings.AddString("vendor", configuration->info.vendor); 174 screenSettings.AddString("name", configuration->info.name); 175 screenSettings.AddInt32("product id", 176 configuration->info.product_id); 177 screenSettings.AddString("serial", 178 configuration->info.serial_number); 179 screenSettings.AddInt32("produced week", 180 configuration->info.produced.week); 181 screenSettings.AddInt32("produced year", 182 configuration->info.produced.year); 183 } 184 185 screenSettings.AddRect("frame", configuration->frame); 186 screenSettings.AddData("mode", B_RAW_TYPE, &configuration->mode, 187 sizeof(display_mode)); 188 189 settings.AddMessage("screen", &screenSettings); 190 } 191 192 return B_OK; 193 } 194 195 196 status_t 197 ScreenConfigurations::Restore(const BMessage& settings) 198 { 199 fConfigurations.MakeEmpty(); 200 201 BMessage stored; 202 for (int32 i = 0; settings.FindMessage("screen", i, &stored) == B_OK; i++) { 203 const display_mode* mode; 204 ssize_t size; 205 int32 id; 206 if (stored.FindInt32("id", &id) != B_OK 207 || stored.FindData("mode", B_RAW_TYPE, (const void**)&mode, 208 &size) != B_OK 209 || size != sizeof(display_mode)) 210 continue; 211 212 screen_configuration* configuration 213 = new(std::nothrow) screen_configuration; 214 if (configuration == NULL) 215 return B_NO_MEMORY; 216 217 configuration->id = id; 218 configuration->is_current = false; 219 220 const char* vendor; 221 const char* name; 222 uint32 productID; 223 const char* serial; 224 int32 week, year; 225 if (stored.FindString("vendor", &vendor) == B_OK 226 && stored.FindString("name", &name) == B_OK 227 && stored.FindInt32("product id", (int32*)&productID) == B_OK 228 && stored.FindString("serial", &serial) == B_OK 229 && stored.FindInt32("produced week", &week) == B_OK 230 && stored.FindInt32("produced year", &year) == B_OK) { 231 // create monitor info 232 strlcpy(configuration->info.vendor, vendor, 233 sizeof(configuration->info.vendor)); 234 strlcpy(configuration->info.name, name, sizeof(configuration->info.name)); 235 strlcpy(configuration->info.serial_number, serial, 236 sizeof(configuration->info.serial_number)); 237 configuration->info.product_id = productID; 238 configuration->info.produced.week = week; 239 configuration->info.produced.year = year; 240 configuration->has_info = true; 241 } else 242 configuration->has_info = false; 243 244 stored.FindRect("frame", &configuration->frame); 245 memcpy(&configuration->mode, mode, sizeof(display_mode)); 246 247 fConfigurations.AddItem(configuration); 248 } 249 250 return B_OK; 251 } 252