1 /*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "metadata/CameraMetaData.h"
22 #include "common/Common.h" // for uint32_t, trimSpaces
23 #include "metadata/Camera.h" // for Camera
24 #include "metadata/CameraMetadataException.h" // for ThrowCME
25 #include <algorithm> // for find_if
26 #include <map> // for _Rb_tree_iterator, map
27 #include <string> // for string, operator==
28 #include <utility> // for pair
29 #include <vector> // for vector
30
31 #ifdef HAVE_PUGIXML
32 #include <pugixml.hpp> // for xml_document, xml_pars...
33 using pugi::xml_node;
34 using pugi::xml_document;
35 using pugi::xml_parse_result;
36 #endif
37
38 using std::string;
39
40 namespace rawspeed {
41
42 #ifdef HAVE_PUGIXML
CameraMetaData(const char * docname)43 CameraMetaData::CameraMetaData(const char *docname) {
44 xml_document doc;
45
46 #if defined(__unix__) || defined(__APPLE__)
47 xml_parse_result result = doc.load_file(docname);
48 #else
49 xml_parse_result result = doc.load_file(pugi::as_wide(docname).c_str());
50 #endif
51
52 if (!result) {
53 ThrowCME(
54 "XML Document \"%s\" could not be parsed successfully. Error was: %s in %s",
55 docname, result.description(), doc.child("node").attribute("attr").value());
56 }
57
58 for (xml_node camera : doc.child("Cameras").children("Camera")) {
59 const auto* cam = addCamera(std::make_unique<Camera>(camera));
60
61 if (cam == nullptr)
62 continue;
63
64 // Create cameras for aliases.
65 for (auto i = 0UL; i < cam->aliases.size(); i++) {
66 addCamera(std::make_unique<Camera>(cam, i));
67 }
68 }
69 }
70 #endif
71
getId(const string & make,const string & model,const string & mode)72 static inline CameraId getId(const string& make, const string& model,
73 const string& mode) {
74 CameraId id;
75 id.make = trimSpaces(make);
76 id.model = trimSpaces(model);
77 id.mode = trimSpaces(mode);
78
79 return id;
80 }
81
getCamera(const string & make,const string & model,const string & mode) const82 const Camera* CameraMetaData::getCamera(const string& make, const string& model,
83 const string& mode) const {
84 auto camera = cameras.find(getId(make, model, mode));
85 return camera == cameras.end() ? nullptr : camera->second.get();
86 }
87
getCamera(const string & make,const string & model) const88 const Camera* CameraMetaData::getCamera(const string& make,
89 const string& model) const {
90 auto id = getId(make, model, "");
91
92 auto iter = find_if(cameras.cbegin(), cameras.cend(),
93 [&id](decltype(*cameras.cbegin())& i) -> bool {
94 const auto& cid = i.first;
95 return tie(id.make, id.model) ==
96 tie(cid.make, cid.model);
97 });
98
99 if (iter == cameras.end())
100 return nullptr;
101
102 return iter->second.get();
103 }
104
hasCamera(const string & make,const string & model,const string & mode) const105 bool CameraMetaData::hasCamera(const string& make, const string& model,
106 const string& mode) const {
107 return getCamera(make, model, mode);
108 }
109
110 const Camera* __attribute__((pure))
getChdkCamera(uint32_t filesize) const111 CameraMetaData::getChdkCamera(uint32_t filesize) const {
112 auto camera = chdkCameras.find(filesize);
113 return camera == chdkCameras.end() ? nullptr : camera->second;
114 }
115
116 bool __attribute__((pure))
hasChdkCamera(uint32_t filesize) const117 CameraMetaData::hasChdkCamera(uint32_t filesize) const {
118 return chdkCameras.end() != chdkCameras.find(filesize);
119 }
120
addCamera(std::unique_ptr<Camera> cam)121 const Camera* CameraMetaData::addCamera(std::unique_ptr<Camera> cam) {
122 auto id = getId(cam->make, cam->model, cam->mode);
123 if (cameras.end() != cameras.find(id)) {
124 writeLog(
125 DEBUG_PRIO_WARNING,
126 "CameraMetaData: Duplicate entry found for camera: %s %s, Skipping!",
127 cam->make.c_str(), cam->model.c_str());
128 return nullptr;
129 }
130 cameras[id] = std::move(cam);
131
132 if (string::npos != cameras[id]->mode.find("chdk")) {
133 auto filesize_hint = cameras[id]->hints.get("filesize", string());
134 if (filesize_hint.empty()) {
135 writeLog(DEBUG_PRIO_WARNING,
136 "CameraMetaData: CHDK camera: %s %s, no \"filesize\" hint set!",
137 cameras[id]->make.c_str(), cameras[id]->model.c_str());
138 } else {
139 chdkCameras[stoi(filesize_hint)] = cameras[id].get();
140 // writeLog(DEBUG_PRIO_WARNING, "CHDK camera: %s %s size:%u",
141 // cameras[id]->make.c_str(), cameras[id]->model.c_str(), size);
142 }
143 }
144 return cameras[id].get();
145 }
146
disableMake(const string & make)147 void CameraMetaData::disableMake(const string &make) {
148 for (const auto& cam : cameras) {
149 if (cam.second->make == make)
150 cam.second->supported = false;
151 }
152 }
153
disableCamera(const string & make,const string & model)154 void CameraMetaData::disableCamera(const string &make, const string &model) {
155 for (const auto& cam : cameras) {
156 if (cam.second->make == make && cam.second->model == model)
157 cam.second->supported = false;
158 }
159 }
160
161 } // namespace rawspeed
162