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 12 #include <Message.h> 13 14 15 ScreenConfigurations::ScreenConfigurations() 16 : 17 fConfigurations(10, true) 18 { 19 } 20 21 22 ScreenConfigurations::~ScreenConfigurations() 23 { 24 } 25 26 27 screen_configuration* 28 ScreenConfigurations::CurrentByID(int32 id) const 29 { 30 for (int32 i = fConfigurations.CountItems(); i-- > 0;) { 31 screen_configuration* configuration = fConfigurations.ItemAt(i); 32 33 if (configuration->id == id && configuration->is_current) 34 return configuration; 35 } 36 37 return NULL; 38 } 39 40 41 screen_configuration* 42 ScreenConfigurations::BestFit(int32 id, const monitor_info* info, 43 bool* _exactMatch) const 44 { 45 if (info == NULL) { 46 // Only look for a matching ID - this is all we have 47 for (uint32 pass = 0; pass < 2; pass++) { 48 for (int32 i = fConfigurations.CountItems(); i-- > 0;) { 49 screen_configuration* configuration = fConfigurations.ItemAt(i); 50 51 if ((pass != 0 || !configuration->has_info) 52 && id == configuration->id) 53 return configuration; 54 } 55 } 56 57 return NULL; 58 } 59 60 // Look for a configuration that matches the monitor 61 62 bool exactMatch = false; 63 int32 bestScore = 0; 64 int32 bestIndex = -1; 65 BMessage stored; 66 67 for (int32 i = fConfigurations.CountItems(); i-- > 0;) { 68 screen_configuration* configuration = fConfigurations.ItemAt(i); 69 if (!configuration->has_info) 70 continue; 71 72 int32 score = 0; 73 74 if (!strcasecmp(configuration->info.vendor, info->vendor) 75 && !strcasecmp(configuration->info.name, info->name) 76 && configuration->info.product_id == info->product_id) { 77 score += 2; 78 if (info->serial_number[0] != '\0' 79 && !strcmp(configuration->info.serial_number, 80 info->serial_number)) { 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 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 147 ScreenConfigurations::Remove(screen_configuration* configuration) 148 { 149 if (configuration == NULL) 150 return; 151 152 fConfigurations.RemoveItem(configuration); 153 // this also deletes the configuration 154 } 155 156 157 /*! Stores all configurations as separate BMessages into the provided 158 \a settings container. 159 */ 160 status_t 161 ScreenConfigurations::Store(BMessage& settings) const 162 { 163 // Store the configuration of all current screens 164 165 for (int32 i = 0; i < fConfigurations.CountItems(); i++) { 166 screen_configuration* configuration = fConfigurations.ItemAt(i); 167 168 BMessage screenSettings; 169 screenSettings.AddInt32("id", configuration->id); 170 171 if (configuration->has_info) { 172 screenSettings.AddString("vendor", configuration->info.vendor); 173 screenSettings.AddString("name", configuration->info.name); 174 screenSettings.AddInt32("product id", 175 configuration->info.product_id); 176 screenSettings.AddString("serial", 177 configuration->info.serial_number); 178 screenSettings.AddInt32("produced week", 179 configuration->info.produced.week); 180 screenSettings.AddInt32("produced year", 181 configuration->info.produced.year); 182 } 183 184 screenSettings.AddRect("frame", configuration->frame); 185 screenSettings.AddData("mode", B_RAW_TYPE, &configuration->mode, 186 sizeof(display_mode)); 187 188 settings.AddMessage("screen", &screenSettings); 189 } 190 191 return B_OK; 192 } 193 194 195 status_t 196 ScreenConfigurations::Restore(const BMessage& settings) 197 { 198 fConfigurations.MakeEmpty(); 199 200 BMessage stored; 201 for (int32 i = 0; settings.FindMessage("screen", i, &stored) == B_OK; i++) { 202 const display_mode* mode; 203 ssize_t size; 204 int32 id; 205 if (stored.FindInt32("id", &id) != B_OK 206 || stored.FindData("mode", B_RAW_TYPE, (const void**)&mode, 207 &size) != B_OK 208 || size != sizeof(display_mode)) 209 continue; 210 211 screen_configuration* configuration 212 = new(std::nothrow) screen_configuration; 213 if (configuration == NULL) 214 return B_NO_MEMORY; 215 216 configuration->id = id; 217 configuration->is_current = false; 218 219 const char* vendor; 220 const char* name; 221 uint32 productID; 222 const char* serial; 223 int32 week, year; 224 if (stored.FindString("vendor", &vendor) == B_OK 225 && stored.FindString("name", &name) == B_OK 226 && stored.FindInt32("product id", (int32*)&productID) == B_OK 227 && stored.FindString("serial", &serial) == B_OK 228 && stored.FindInt32("produced week", &week) == B_OK 229 && stored.FindInt32("produced year", &year) == B_OK) { 230 // create monitor info 231 strlcpy(configuration->info.vendor, vendor, 232 sizeof(configuration->info.vendor)); 233 strlcpy(configuration->info.name, name, sizeof(configuration->info.name)); 234 strlcpy(configuration->info.serial_number, serial, 235 sizeof(configuration->info.serial_number)); 236 configuration->info.product_id = productID; 237 configuration->info.produced.week = week; 238 configuration->info.produced.year = year; 239 configuration->has_info = true; 240 } else 241 configuration->has_info = false; 242 243 stored.FindRect("frame", &configuration->frame); 244 memcpy(&configuration->mode, mode, sizeof(display_mode)); 245 246 fConfigurations.AddItem(configuration); 247 } 248 249 return B_OK; 250 } 251