root / utils / dc-ctl / dc-ctl.cpp @ b3e6d144
History | View | Annotate | Download (16.2 kB)
| 1 |
|
|---|---|
| 2 |
#include <iostream> |
| 3 |
#include <fstream> |
| 4 |
#include <string> |
| 5 |
#include <stdexcept> |
| 6 |
#include <dc1394/dc1394.h> |
| 7 |
#include <libraw1394/raw1394.h> |
| 8 |
#include <boost/program_options.hpp> |
| 9 |
#include <boost/tokenizer.hpp> |
| 10 |
#include <boost/foreach.hpp> |
| 11 |
|
| 12 |
|
| 13 |
int featureMin(const dc1394featureset_t &features, dc1394feature_t feature) |
| 14 |
{
|
| 15 |
return features.feature[feature - DC1394_FEATURE_MIN].min;
|
| 16 |
} |
| 17 |
|
| 18 |
int featureMax(const dc1394featureset_t &features, dc1394feature_t feature) |
| 19 |
{
|
| 20 |
return features.feature[feature - DC1394_FEATURE_MIN].max;
|
| 21 |
} |
| 22 |
|
| 23 |
void setFeature(dc1394camera_t *camera, const dc1394featureset_t &features, |
| 24 |
dc1394feature_t feature, const std::string &valueStr) |
| 25 |
{
|
| 26 |
using boost::lexical_cast;
|
| 27 |
const uint32_t MIN = featureMin(features, feature);
|
| 28 |
const uint32_t MAX = featureMax(features, feature);
|
| 29 |
dc1394error_t camerr; |
| 30 |
|
| 31 |
if (valueStr == "auto") |
| 32 |
{
|
| 33 |
camerr = dc1394_feature_set_mode(camera, feature, DC1394_FEATURE_MODE_AUTO); |
| 34 |
if (camerr != DC1394_SUCCESS)
|
| 35 |
throw std::runtime_error("libdc1394 error: this should be more verbose"); |
| 36 |
} |
| 37 |
else
|
| 38 |
{
|
| 39 |
dc1394_feature_set_mode(camera, feature, DC1394_FEATURE_MODE_MANUAL); |
| 40 |
const uint32_t value = lexical_cast<int>(valueStr); |
| 41 |
|
| 42 |
camerr = dc1394_feature_set_mode(camera, feature, DC1394_FEATURE_MODE_MANUAL); |
| 43 |
if (camerr != DC1394_SUCCESS)
|
| 44 |
throw std::runtime_error("libdc1394 error: this should be more verbose"); |
| 45 |
if (value >= MIN and value <= MAX) |
| 46 |
dc1394_feature_set_value(camera, feature, value); |
| 47 |
else
|
| 48 |
{
|
| 49 |
std::cerr << "error: value must be in range [" << MIN << "," << MAX << "], ignoring\n"; |
| 50 |
} |
| 51 |
} |
| 52 |
} |
| 53 |
|
| 54 |
unsigned int getFeatureValue(dc1394feature_t feature, dc1394camera_t * camera) |
| 55 |
{
|
| 56 |
unsigned int value; |
| 57 |
dc1394error_t error = dc1394_feature_get_value(camera, feature, &value); |
| 58 |
if (error != DC1394_SUCCESS)
|
| 59 |
throw std::runtime_error("libdc1394 error: could not get value"); |
| 60 |
return value;
|
| 61 |
} |
| 62 |
|
| 63 |
|
| 64 |
/// pass by reference because we're expecting multiple values, alternately could return a vector
|
| 65 |
std::string getWhiteBalance(dc1394camera_t * camera)
|
| 66 |
{
|
| 67 |
unsigned int valueBU, valueRV; |
| 68 |
dc1394error_t error = dc1394_feature_whitebalance_get_value(camera, &valueBU, &valueRV); |
| 69 |
if (error != DC1394_SUCCESS)
|
| 70 |
throw std::runtime_error("libdc1394 error: could not get value"); |
| 71 |
std::ostringstream result; |
| 72 |
result << valueBU << "," << valueRV;
|
| 73 |
return result.str();
|
| 74 |
} |
| 75 |
|
| 76 |
|
| 77 |
void saveSettings(const std::string &filename, dc1394camera_t * camera) |
| 78 |
{
|
| 79 |
std::cout << "Saving settings to " << filename << std::endl;
|
| 80 |
/// FIXME: find reference on how to safely, idiomatically open and write to a file
|
| 81 |
std::ofstream fout; |
| 82 |
try
|
| 83 |
{
|
| 84 |
fout.open(filename.c_str()); |
| 85 |
fout << "camera=" << std::hex << camera->guid << "\n" << std::dec; |
| 86 |
fout << "brightness=" << getFeatureValue(DC1394_FEATURE_BRIGHTNESS, camera) << "\n"; |
| 87 |
fout << "auto-exposure=" << getFeatureValue(DC1394_FEATURE_EXPOSURE, camera) << "\n"; |
| 88 |
fout << "sharpness=" << getFeatureValue(DC1394_FEATURE_SHARPNESS, camera) << "\n"; |
| 89 |
fout << "whitebalance=" << getWhiteBalance(camera) << "\n"; |
| 90 |
fout << "saturation=" << getFeatureValue(DC1394_FEATURE_SATURATION, camera) << "\n"; |
| 91 |
fout << "gamma=" << getFeatureValue(DC1394_FEATURE_GAMMA, camera) << "\n"; |
| 92 |
fout << "shutter-time=" << getFeatureValue(DC1394_FEATURE_SHUTTER, camera) << "\n"; |
| 93 |
fout << "gain=" << getFeatureValue(DC1394_FEATURE_GAIN, camera) << "\n"; |
| 94 |
fout.close(); |
| 95 |
} |
| 96 |
catch (const std::exception& e) // catch it here so that we close file |
| 97 |
{
|
| 98 |
std::cerr << "error: " << e.what() << "\n"; |
| 99 |
} |
| 100 |
fout.close(); |
| 101 |
} |
| 102 |
|
| 103 |
std::string featureHelp(const dc1394featureset_t &features, dc1394feature_t feature) |
| 104 |
{
|
| 105 |
using std::string; |
| 106 |
using boost::lexical_cast;
|
| 107 |
string helpStr;
|
| 108 |
|
| 109 |
switch (feature)
|
| 110 |
{
|
| 111 |
case DC1394_FEATURE_BRIGHTNESS:
|
| 112 |
helpStr = "brightness [";
|
| 113 |
break;
|
| 114 |
case DC1394_FEATURE_EXPOSURE:
|
| 115 |
helpStr = "auto-exposure [";
|
| 116 |
break;
|
| 117 |
case DC1394_FEATURE_SHARPNESS:
|
| 118 |
helpStr = "sharpness [";
|
| 119 |
break;
|
| 120 |
case DC1394_FEATURE_WHITE_BALANCE:
|
| 121 |
helpStr = "Blue/U Red/V [";
|
| 122 |
helpStr += lexical_cast<string>(features.feature[feature - DC1394_FEATURE_MIN].min);
|
| 123 |
helpStr += ",";
|
| 124 |
helpStr += lexical_cast<string>(features.feature[feature - DC1394_FEATURE_MIN].max) + "]"; |
| 125 |
helpStr += " [" + lexical_cast<string>(features.feature[feature - DC1394_FEATURE_MIN].min); |
| 126 |
helpStr += ",";
|
| 127 |
helpStr += lexical_cast<string>(features.feature[feature - DC1394_FEATURE_MIN].max) + "]"; |
| 128 |
return helpStr;
|
| 129 |
case DC1394_FEATURE_SATURATION:
|
| 130 |
helpStr = "saturation [";
|
| 131 |
break;
|
| 132 |
case DC1394_FEATURE_GAMMA:
|
| 133 |
helpStr = "gamma [";
|
| 134 |
break;
|
| 135 |
case DC1394_FEATURE_SHUTTER:
|
| 136 |
helpStr = "shutter-time [";
|
| 137 |
break;
|
| 138 |
case DC1394_FEATURE_GAIN:
|
| 139 |
helpStr = "gain (db) [";
|
| 140 |
break;
|
| 141 |
default:
|
| 142 |
std::cerr << "Unknown feature " << feature;
|
| 143 |
break;
|
| 144 |
} |
| 145 |
|
| 146 |
helpStr += lexical_cast<string>(features.feature[feature - DC1394_FEATURE_MIN].min);
|
| 147 |
helpStr += ",";
|
| 148 |
helpStr += lexical_cast<string>(features.feature[feature - DC1394_FEATURE_MIN].max) + "]"; |
| 149 |
return helpStr;
|
| 150 |
} |
| 151 |
|
| 152 |
|
| 153 |
void cleanup(dc1394_t * dc1394, dc1394camera_t *camera, dc1394camera_list_t *cameras)
|
| 154 |
{
|
| 155 |
if (camera != 0) |
| 156 |
free(camera); |
| 157 |
if (cameras != 0) |
| 158 |
dc1394_camera_free_list(cameras); |
| 159 |
if (dc1394 != 0) |
| 160 |
dc1394_free(dc1394); |
| 161 |
} |
| 162 |
|
| 163 |
|
| 164 |
int run(int argc, char *argv[]) |
| 165 |
{
|
| 166 |
dc1394_t * dc1394 = 0;
|
| 167 |
dc1394camera_t *camera = 0;
|
| 168 |
dc1394camera_list_t *cameras = 0;
|
| 169 |
|
| 170 |
try
|
| 171 |
{
|
| 172 |
namespace po = boost::program_options;
|
| 173 |
using std::string; |
| 174 |
using boost::lexical_cast;
|
| 175 |
using boost::tokenizer;
|
| 176 |
using boost::char_separator;
|
| 177 |
po::options_description desc("Allowed options");
|
| 178 |
|
| 179 |
// make sure raw1394 is loaded and read/writeable
|
| 180 |
raw1394handle_t tmp_handle = raw1394_new_handle(); |
| 181 |
if (tmp_handle == NULL) |
| 182 |
{
|
| 183 |
throw std::runtime_error("Warning: could not get a handle to your IEEE1394 card.\n\n" |
| 184 |
"Please check that:\n- the card is present\n- the IEEE1394 modules (ieee1394,"
|
| 185 |
"ohci1394,\n raw1394 and video1394) are loaded\n- you have read/write "
|
| 186 |
"permissions on the\n /dev/raw1394 and /dev/video1394 devices.");
|
| 187 |
} |
| 188 |
else
|
| 189 |
raw1394_destroy_handle(tmp_handle); |
| 190 |
|
| 191 |
// get camera information first to have valid ranges
|
| 192 |
dc1394error_t camerr; |
| 193 |
dc1394 = dc1394_new(); |
| 194 |
camerr = dc1394_camera_enumerate(dc1394, &cameras); |
| 195 |
if (camerr != DC1394_SUCCESS)
|
| 196 |
throw std::runtime_error("libdc1394 error: this should be more verbose"); |
| 197 |
if (cameras->num == 0) |
| 198 |
throw std::runtime_error("libdc1394 error: no camera found on bus"); |
| 199 |
|
| 200 |
camera = dc1394_camera_new_unit(dc1394, cameras->ids[0].guid,
|
| 201 |
cameras->ids[0].unit);
|
| 202 |
|
| 203 |
dc1394featureset_t features; |
| 204 |
camerr = dc1394_feature_get_all(camera, &features); |
| 205 |
if (camerr != DC1394_SUCCESS)
|
| 206 |
throw std::runtime_error("libdc1394 error: this should be more verbose"); |
| 207 |
|
| 208 |
// FIXME: right now we can only use camera 0. But we can't display the valid ranges in the help if we
|
| 209 |
// don't know ahead of time which camera to use.
|
| 210 |
|
| 211 |
// using strings so that value can be "auto"
|
| 212 |
desc.add_options() |
| 213 |
("help,h", "produce help message") |
| 214 |
("camera,c", po::value<string>()->default_value("0"), "guid of camera number to use (0 is first camera on bus)") |
| 215 |
("brightness,b", po::value<string>(), featureHelp(features, DC1394_FEATURE_BRIGHTNESS).c_str()) |
| 216 |
("auto-exposure,e", po::value<string>(), featureHelp(features, DC1394_FEATURE_EXPOSURE).c_str()) |
| 217 |
("sharpness,s", po::value<string>(), featureHelp(features, DC1394_FEATURE_SHARPNESS).c_str()) |
| 218 |
("whitebalance,w", po::value<string>(), featureHelp(features, DC1394_FEATURE_WHITE_BALANCE).c_str()) |
| 219 |
("saturation,S", po::value<string>(), featureHelp(features, DC1394_FEATURE_SATURATION).c_str()) |
| 220 |
("gamma,g", po::value<string>(), featureHelp(features, DC1394_FEATURE_GAMMA).c_str()) |
| 221 |
("shutter-time,t", po::value<string>(), featureHelp(features, DC1394_FEATURE_SHUTTER).c_str()) |
| 222 |
("gain,G", po::value<string>(), featureHelp(features, DC1394_FEATURE_GAIN).c_str()) |
| 223 |
("config,C", po::value<string>(), "path of file with configuration presets") |
| 224 |
("list-features,l", po::bool_switch(), "print available features for this camera") |
| 225 |
("save,x", po::value<string>(), "save current camera settings to the specified filename") |
| 226 |
; |
| 227 |
|
| 228 |
po::variables_map vm; |
| 229 |
po::store(po::parse_command_line(argc, argv, desc), vm); |
| 230 |
po::notify(vm); |
| 231 |
|
| 232 |
if (vm.count("help") or argc == 1) // no args |
| 233 |
{
|
| 234 |
std::cout << desc << "\n";
|
| 235 |
cleanup(dc1394, camera, cameras); |
| 236 |
return 0; |
| 237 |
} |
| 238 |
|
| 239 |
if(vm.count("save")) |
| 240 |
{
|
| 241 |
saveSettings(vm["save"].as<string>(), camera); |
| 242 |
cleanup(dc1394, camera, cameras); |
| 243 |
return 0; |
| 244 |
} |
| 245 |
|
| 246 |
if(vm.count("config")) |
| 247 |
{
|
| 248 |
std::ifstream configFile(vm["config"].as<string>().c_str()); |
| 249 |
store(parse_config_file(configFile, desc), vm); |
| 250 |
} |
| 251 |
|
| 252 |
if (vm["camera"].as<string>() != "0") // using non-default camera id |
| 253 |
{
|
| 254 |
// find right guid
|
| 255 |
bool matchedGUID = false; |
| 256 |
for (unsigned i = 0; i < cameras->num and not matchedGUID; ++i) |
| 257 |
{
|
| 258 |
std::stringstream GUIDInHex; |
| 259 |
GUIDInHex << std::hex << cameras->ids[i].guid; |
| 260 |
if (GUIDInHex.str() == vm["camera"].as<string>()) |
| 261 |
{
|
| 262 |
camera = dc1394_camera_new_unit(dc1394, cameras->ids[i].guid, |
| 263 |
cameras->ids[i].unit); |
| 264 |
matchedGUID = true;
|
| 265 |
} |
| 266 |
} |
| 267 |
if (not matchedGUID) |
| 268 |
throw std::runtime_error("could not find camera with guid " + |
| 269 |
lexical_cast<string>(vm["camera"].as<string>())); |
| 270 |
|
| 271 |
|
| 272 |
camerr = dc1394_feature_get_all(camera, &features); |
| 273 |
if (camerr != DC1394_SUCCESS)
|
| 274 |
throw std::runtime_error("libdc1394 error: this should be more verbose"); |
| 275 |
} |
| 276 |
|
| 277 |
if (vm["list-features"].as<bool>()) |
| 278 |
{
|
| 279 |
camerr = dc1394_feature_print_all(&features, stdout); |
| 280 |
// FIXME: actually look at the error value
|
| 281 |
if (camerr != DC1394_SUCCESS)
|
| 282 |
throw std::runtime_error("libdc1394 error: could not print features"); |
| 283 |
std::cout << std::endl; |
| 284 |
cleanup(dc1394, camera, cameras); |
| 285 |
return 0; |
| 286 |
} |
| 287 |
|
| 288 |
if(vm.count("brightness")) |
| 289 |
{
|
| 290 |
std::cout << "Setting brightness: " << vm["brightness"].as<string>() << std::endl; |
| 291 |
setFeature(camera, features, DC1394_FEATURE_BRIGHTNESS, vm["brightness"].as<string>()); |
| 292 |
} |
| 293 |
|
| 294 |
if(vm.count("auto-exposure")) |
| 295 |
{
|
| 296 |
std::cout << "Setting auto-exposure: " << vm["auto-exposure"].as<string>() << std::endl; |
| 297 |
setFeature(camera, features, DC1394_FEATURE_EXPOSURE, vm["auto-exposure"].as<string>()); |
| 298 |
} |
| 299 |
|
| 300 |
if(vm.count("sharpness")) |
| 301 |
{
|
| 302 |
std::cout << "Setting sharpness: " << vm["sharpness"].as<string>() << std::endl; |
| 303 |
setFeature(camera, features, DC1394_FEATURE_SHARPNESS, vm["sharpness"].as<string>()); |
| 304 |
} |
| 305 |
|
| 306 |
if (vm.count("whitebalance")) |
| 307 |
{
|
| 308 |
// FIXME: Hack because i don't know how to have defaults for vector program options
|
| 309 |
string u_b_string;
|
| 310 |
string v_r_string;
|
| 311 |
bool autoWhiteBalance = false; |
| 312 |
|
| 313 |
// either auto or values
|
| 314 |
if (vm["whitebalance"].as<string>() == "auto") |
| 315 |
{
|
| 316 |
camerr = dc1394_feature_set_mode(camera, DC1394_FEATURE_WHITE_BALANCE, DC1394_FEATURE_MODE_AUTO); |
| 317 |
if (camerr != DC1394_SUCCESS)
|
| 318 |
throw std::runtime_error("libdc1394 error: this should be more verbose"); |
| 319 |
autoWhiteBalance = true;
|
| 320 |
std::cout << "Setting whitebalance: auto\n";
|
| 321 |
} |
| 322 |
else // need to parse tokens |
| 323 |
{
|
| 324 |
char_separator<char> sep(","); |
| 325 |
tokenizer< char_separator<char> > tokens(vm["whitebalance"].as<string>(), sep); |
| 326 |
int count = 0; |
| 327 |
BOOST_FOREACH(string t, tokens)
|
| 328 |
{
|
| 329 |
switch (count)
|
| 330 |
{
|
| 331 |
case 0: |
| 332 |
u_b_string = t; |
| 333 |
break;
|
| 334 |
case 1: |
| 335 |
v_r_string = t; |
| 336 |
break;
|
| 337 |
default:
|
| 338 |
std::cerr << "error: white balance takes two arguments, Blue/U and Red/V [int int]\n";
|
| 339 |
cleanup(dc1394, camera, cameras); |
| 340 |
return 1; |
| 341 |
} |
| 342 |
++count; |
| 343 |
} |
| 344 |
} |
| 345 |
|
| 346 |
if (not autoWhiteBalance) |
| 347 |
{
|
| 348 |
const int MIN_WHITE_BALANCE = featureMin(features, DC1394_FEATURE_WHITE_BALANCE); |
| 349 |
const int MAX_WHITE_BALANCE = featureMax(features, DC1394_FEATURE_WHITE_BALANCE); |
| 350 |
const int u_b = lexical_cast<int>(u_b_string); // convert to ints |
| 351 |
const int v_r = lexical_cast<int>(v_r_string); // convert to ints |
| 352 |
|
| 353 |
if (u_b >= MIN_WHITE_BALANCE and |
| 354 |
u_b <= MAX_WHITE_BALANCE and
|
| 355 |
v_r >= MIN_WHITE_BALANCE and
|
| 356 |
v_r <= MAX_WHITE_BALANCE) |
| 357 |
{
|
| 358 |
std::cout << "Setting white balance: Blue/U=" << u_b << ", Red/V=" << v_r << "\n"; |
| 359 |
camerr = dc1394_feature_set_mode(camera, DC1394_FEATURE_WHITE_BALANCE, DC1394_FEATURE_MODE_MANUAL); |
| 360 |
camerr = dc1394_feature_whitebalance_set_value(camera, u_b, v_r); |
| 361 |
if (camerr != DC1394_SUCCESS)
|
| 362 |
throw std::runtime_error("libdc1394 error: this should be more verbose"); |
| 363 |
} |
| 364 |
else
|
| 365 |
{
|
| 366 |
std::cerr << "error: whitebalance values must be in range ["
|
| 367 |
<< MIN_WHITE_BALANCE << "," << MAX_WHITE_BALANCE << "]" << std::endl; |
| 368 |
cleanup(dc1394, camera, cameras); |
| 369 |
return 1; |
| 370 |
} |
| 371 |
} |
| 372 |
} |
| 373 |
|
| 374 |
if (vm.count("saturation")) |
| 375 |
{
|
| 376 |
std::cout << "Setting saturation : " << vm["saturation"].as<string>() << std::endl; |
| 377 |
setFeature(camera, features, DC1394_FEATURE_SATURATION, vm["saturation"].as<string>()); |
| 378 |
} |
| 379 |
|
| 380 |
if (vm.count("gamma")) |
| 381 |
{
|
| 382 |
std::cout << "Setting gamma: " << vm["gamma"].as<string>() << std::endl; |
| 383 |
setFeature(camera, features, DC1394_FEATURE_GAMMA, vm["gamma"].as<string>()); |
| 384 |
} |
| 385 |
|
| 386 |
if (vm.count("shutter-time")) |
| 387 |
{
|
| 388 |
std::cout << "Setting shutter-time: " << vm["shutter-time"].as<string>() << std::endl; |
| 389 |
setFeature(camera, features, DC1394_FEATURE_SHUTTER, vm["shutter-time"].as<string>()); |
| 390 |
} |
| 391 |
|
| 392 |
if (vm.count("gain")) |
| 393 |
{
|
| 394 |
std::cout << "Setting gain : " << vm["gain"].as<string>() << std::endl; |
| 395 |
setFeature(camera, features, DC1394_FEATURE_GAIN, vm["gain"].as<string>()); |
| 396 |
} |
| 397 |
} |
| 398 |
catch (const std::exception& e) |
| 399 |
{
|
| 400 |
std::cerr << "error: " << e.what() << "\n"; |
| 401 |
cleanup(dc1394, camera, cameras); |
| 402 |
return 1; |
| 403 |
} |
| 404 |
catch (...)
|
| 405 |
{
|
| 406 |
// FIXME: is this possible?
|
| 407 |
std::cerr << "Exception of unknown type!\n";
|
| 408 |
cleanup(dc1394, camera, cameras); |
| 409 |
return 1; |
| 410 |
} |
| 411 |
|
| 412 |
cleanup(dc1394, camera, cameras); |
| 413 |
return 0; |
| 414 |
} |
| 415 |
|
| 416 |
// FIXME: i should grab the error return codes from all the libdc calls and check them
|
| 417 |
int main(int argc, char *argv[]) |
| 418 |
{
|
| 419 |
return run(argc, argv);
|
| 420 |
} |
| 421 |
|
