This URL has Read-Only access.

Statistics
| Branch: | Tag: | Revision:

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