GenericGrabber.cpp

GenericGrabber with added support - Christof Elbrechter, 2012-09-17 13:44

Download (35.1 KB)

 
1
/********************************************************************
2
**                Image Component Library (ICL)                    **
3
**                                                                 **
4
** Copyright (C) 2006-2012 CITEC, University of Bielefeld          **
5
**                         Neuroinformatics Group                  **
6
** Website: www.iclcv.org and                                      **
7
**          http://opensource.cit-ec.de/projects/icl               **
8
**                                                                 **
9
** File   : ICLIO/src/GenericGrabber.cpp                           **
10
** Module : ICLIO                                                  **
11
** Authors: Christof Elbrechter                                    **
12
**                                                                 **
13
**                                                                 **
14
** Commercial License                                              **
15
** ICL can be used commercially, please refer to our website       **
16
** www.iclcv.org for more details.                                 **
17
**                                                                 **
18
** GNU General Public License Usage                                **
19
** Alternatively, this file may be used under the terms of the     **
20
** GNU General Public License version 3.0 as published by the      **
21
** Free Software Foundation and appearing in the file LICENSE.GPL  **
22
** included in the packaging of this file.  Please review the      **
23
** following information to ensure the GNU General Public License  **
24
** version 3.0 requirements will be met:                           **
25
** http://www.gnu.org/copyleft/gpl.html.                           **
26
**                                                                 **
27
** The development of this software was supported by the           **
28
** Excellence Cluster EXC 277 Cognitive Interaction Technology.    **
29
** The Excellence Cluster EXC 277 is a grant of the Deutsche       **
30
** Forschungsgemeinschaft (DFG) in the context of the German       **
31
** Excellence Initiative.                                          **
32
**                                                                 **
33
*********************************************************************/
34

    
35
#include <ICLIO/GenericGrabber.h>
36
#include <ICLUtils/StringUtils.h>
37
#include <ICLIO/FileGrabber.h>
38
#include <ICLIO/CreateGrabber.h>
39
#include <ICLIO/FileList.h>
40

    
41
#define USE_CRAZY_SURFACE_GRABBER
42
#ifdef USE_CRAZY_SURFACE_GRABBER
43

    
44
#include <stdint.h>
45
#include <usb.h>
46
#include <unistd.h>
47
#include <stdio.h>
48
#include <string.h>
49

    
50
#define ID_MICROSOFT 0x045e
51
#define ID_SURFACE   0x0775
52
#define VIDEO_RES_X 960
53
#define VIDEO_RES_Y 540
54
#define VIDEO_BUFFER_SIZE  VIDEO_RES_X * VIDEO_RES_Y
55
// read 512 bytes from endpoint 0x86 -> get header + blobs
56
struct surface_header {
57
  uint16_t type;  // always 0x0001
58
  uint16_t count; // count of blobs (if == 0: continue prev. packet ID)
59
  uint32_t packet_id;
60
  uint32_t timestamp; // milliseconds (increases by 16 or 17 each frame)
61
  uint32_t unknown;   // "epoch?" always 02/03 00 00 00
62
};
63
struct surface_blob {
64
  uint16_t blob_id;
65
  uint8_t action;     // 0x02 = enter/exit, 0x03 = update (?)
66
  uint8_t unknown;    // always 0x01 or 0x02 (no idea what this is?)
67
  uint16_t bb_pos_x;  // upper left corner of bounding box
68
  uint16_t bb_pos_y;
69
  uint16_t bb_size_x; // size of bounding box
70
  uint16_t bb_size_y;
71
  uint16_t pos_x;     // finger tip position
72
  uint16_t pos_y;
73
  uint16_t ctr_x;     // centroid position
74
  uint16_t ctr_y;
75
  uint16_t axis_x;    // somehow related to major/minor axis, mostly:
76
  uint16_t axis_y;    // axis_x == bb_size_y && axis_y == bb_size_x
77
  float    angle;     // orientation in radians relative to x axis
78
  uint32_t area;      // size in pixels/pressure (?)
79
  uint8_t padding[32];
80
};
81

    
82
std::ostream &operator<<(std::ostream &str, const surface_blob &b){
83
  return str << b.blob_id << ',' //<< b.action << ','
84
    << b.bb_pos_x << ',' << b.bb_pos_y << ',' << b.bb_size_x << ',' << b.bb_size_y << ','
85
    << b.pos_x << ',' << b.pos_y << ',' << b.ctr_x << ',' << b.ctr_y << ','
86
    << b.axis_x << ',' << b.axis_y << ',' << b.angle << ',' << b.area;
87
}
88

    
89
std::istream &operator<<(std::istream &str, surface_blob &b){
90
  return str >> b.blob_id //>> b.action
91
    >> b.bb_pos_x >> b.bb_pos_y >> b.bb_size_x >> b.bb_size_y
92
    >> b.pos_x >> b.pos_y >> b.ctr_x >> b.ctr_y
93
    >> b.axis_x >> b.axis_y >> b.angle >> b.area;
94
}
95

    
96

    
97
// read 512 bytes from endpoint 0x82 -> get header below
98
// continue reading 16k blocks until header.size bytes read
99
struct surface_image {
100
  uint32_t magic;     // "SUBF"
101
  uint32_t packet_id;
102
  uint32_t size;      // always 0x0007e900 = 960x540
103
  uint32_t timestamp; // milliseconds (increases by 16 or 17 each frame)
104
  uint32_t unknown;   // "epoch?" always 02/03 00 00 00
105
};
106

    
107

    
108
// read 8 bytes using control message 0xc0,0xb1,0x00,0x00
109
struct surface_sensors {
110
  uint16_t temp;
111
  uint16_t acc_x;
112
  uint16_t acc_y;
113
  uint16_t acc_z;
114
};
115
// helper to find a device by vendor and product
116
usb_dev_handle* usb_get_device_handle( int vendor, int product );
117
// get device status word
118
int surface_get_status( usb_dev_handle* handle );
119
// get sensor status
120
void surface_get_sensors( usb_dev_handle* handle );
121
// initialization sequence
122
void surface_init( usb_dev_handle* handle );
123
// retrieve raw data from surface
124
int surface_get_image( usb_dev_handle* handle, uint8_t* image );
125
int surface_get_blobs( usb_dev_handle* handle, surface_blob* blob );
126

    
127
static int timeout = 1000;
128
#define ENDPOINT_VIDEO 0x82
129
#define ENDPOINT_BLOBS 0x86
130
#define VIDEO_HEADER_MAGIC 0x46425553
131
#define VIDEO_PACKET_SIZE  16384
132

    
133
/************************* HELPER FUNCTIONS *************************/
134

    
135
usb_dev_handle* usb_get_device_handle( int vendor, int product ) {
136

    
137
  usb_init();
138
  usb_find_busses();
139
  usb_find_devices();
140

    
141
  struct usb_bus* busses = usb_get_busses();
142

    
143
  for (struct usb_bus* bus = busses; bus; bus = bus->next) {
144
    for (struct usb_device* dev = bus->devices; dev; dev = dev->next) {
145
      if ((dev->descriptor.idVendor == vendor) && (dev->descriptor.idProduct == product)) {
146
        usb_dev_handle* handle = usb_open(dev);
147
        if (!handle) return 0;
148
        if (usb_claim_interface( handle, 0 ) < 0) return 0;
149
        return handle;
150
      }
151
    }
152
  }
153
  return 0;
154
}
155

    
156

    
157
/************************** CONTROL STUFF ***************************/
158

    
159
#define SURFACE_GET_VERSION 0xb0 // 12 bytes string
160
#define SURFACE_UNKNOWN1    0xb3 //  5 bytes
161
#define SURFACE_UNKNOWN2    0xc1 // 24 bytes
162

    
163
#define SURFACE_GET_STATUS  0xc5 //  4 bytes state (?)
164
#define SURFACE_GET_SENSORS 0xb1 //  8 bytes sensors
165

    
166
// get version info
167
void surface_get_version( usb_dev_handle* handle, uint16_t index ) {
168
  uint8_t buf[13]; buf[12] = 0;
169
  usb_control_msg( handle, 0xC0, SURFACE_GET_VERSION, 0x00, index, (char*)buf, 12, timeout );
170
  //printf("version string 0x%02x: %s\n", index, buf);
171
}
172

    
173
// get device status word
174
int surface_get_status( usb_dev_handle* handle ) {
175
  uint8_t buf[4];
176
  usb_control_msg( handle, 0xC0, SURFACE_GET_STATUS, 0x00, 0x00, (char*)buf, 4, timeout );
177
  return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
178
}
179

    
180
// get sensor status
181
void surface_get_sensors( usb_dev_handle* handle ) {
182
  surface_sensors sensors;
183
  usb_control_msg( handle, 0xC0, SURFACE_GET_SENSORS, 0x00, 0x00, (char*)(&sensors), 8, timeout );
184
  //printf("temp: %d x: %d y: %d z: %d\n",sensors.temp,sensors.acc_x,sensors.acc_y,sensors.acc_z);
185
}
186

    
187
// other commands
188
void surface_command( usb_dev_handle* handle, uint16_t cmd, uint16_t index, uint16_t len ) {
189
  uint8_t buf[24];
190
  usb_control_msg( handle, 0xC0, cmd, 0x00, index, (char*)buf, len, timeout );
191
  /*
192
  printf("command 0x%02x,0x%02x: ", cmd, index );
193
  for (int i = 0; i < len; i++) printf("0x%02x ", buf[i]);
194
  printf("\n");
195
  */
196
}
197

    
198
// mindless repetition of the microsoft driver's init sequence.
199
// quite probably unnecessary, but leave it like this for now.
200
void surface_init( usb_dev_handle* handle ) {
201

    
202
  //printf("microsoft surface 2.0 open source driver 0.0.1\n");
203

    
204
  surface_get_version(handle, 0x00);
205
  surface_get_version(handle, 0x01);
206
  surface_get_version(handle, 0x02);
207

    
208
  surface_command(handle, SURFACE_UNKNOWN2, 0x00, 24 );
209
  surface_command(handle, SURFACE_UNKNOWN1, 0x00,  5 );
210

    
211
  surface_get_version(handle, 0x03);
212
}
213

    
214

    
215
/************************** IMAGE FUNCTIONS *************************/
216

    
217
int surface_get_image( usb_dev_handle* handle, uint8_t* image ) {
218

    
219
  uint8_t buffer[512];
220
  int result, bufpos = 0;
221

    
222
  result = usb_bulk_read( handle, ENDPOINT_VIDEO, (char*)buffer, sizeof(buffer), timeout );
223
  if (result != sizeof(surface_image)) { printf("transfer size mismatch\n"); return -1; }
224

    
225
  surface_image* header = (surface_image*)buffer;
226
  if (header->magic != VIDEO_HEADER_MAGIC) { printf("image magic mismatch\n"); return -1; }
227
  if (header->size  != VIDEO_BUFFER_SIZE ) { printf("image size  mismatch\n"); return -1; }
228

    
229
  while (bufpos < VIDEO_BUFFER_SIZE) {
230
    result = usb_bulk_read( handle, ENDPOINT_VIDEO, (char*)(image+bufpos), VIDEO_PACKET_SIZE, timeout );
231
    if (result < 0) { printf("error in usb_bulk_read\n"); return result; }
232
    bufpos += result;
233
  }
234

    
235
  return header->timestamp;
236
}
237

    
238

    
239
/************************** BLOB FUNCTIONS **************************/
240

    
241
int surface_get_blobs( usb_dev_handle* handle, surface_blob* outblob ) {
242

    
243
  uint8_t buffer[512];
244
  uint32_t packet_id;
245
  int result;
246

    
247
  int need_blobs = -1;
248
  int current = 0;
249

    
250
  surface_header* header = (surface_header*)buffer;
251
  surface_blob*   inblob = (surface_blob*)(buffer+sizeof(surface_header));
252

    
253
  do {
254

    
255
    result = usb_bulk_read( handle, ENDPOINT_BLOBS, (char*)(buffer), sizeof(buffer), timeout ) - sizeof(surface_header);
256
    if (result < 0) { printf("error in usb_bulk_read\n"); return result; }
257
    if (result % sizeof(surface_blob) != 0) { printf("transfer size mismatch\n"); return -1; }
258
    //printf("id: %x count: %d\n",header->packet_id,header->count);
259

    
260
    // first packet
261
    if (need_blobs == -1) {
262
      need_blobs = header->count;
263
      packet_id = header->packet_id;
264
    }
265

    
266
    // sanity check. when video data is also being retrieved, the packet ID
267
    // will usually increase in the middle of a series instead of at the end.
268
    if (packet_id != header->packet_id) { printf("packet ID mismatch\n"); }
269

    
270
    int packet_blobs = result / sizeof(surface_blob);
271

    
272
    for (int i = 0; i < packet_blobs; i++) outblob[current++] = inblob[i];
273

    
274
  }        while (current < need_blobs);
275

    
276
  return need_blobs;
277
}
278

    
279
namespace icl{
280

    
281
class SurfaceGrabber : public Grabber{
282
  usb_dev_handle * s40;
283
  Img8u image;
284
  std::vector<surface_blob> blobs;
285
public:
286
  SurfaceGrabber(){
287
    s40 = 0;
288
    s40 = usb_get_device_handle( ID_MICROSOFT, ID_SURFACE );
289

    
290
    if(!s40) throw ICLException("unable to initializte Surface Grabber (the crazy one)");
291
    surface_init( s40 );
292

    
293
    image = Img8u(Size(VIDEO_RES_X,VIDEO_RES_Y),1);
294
    blobs.resize(256);
295
  }
296

    
297
  virtual const ImgBase *acquireImage() {
298
    surface_get_image( s40, image.begin(0) );
299
    int bc = surface_get_blobs( s40, blobs.data() );
300
    std::ostringstream str;
301
    str << bc << ';';
302
    for(int i=0;i<bc;++i){
303
      str << blobs[i] << ';';
304
    }
305
    image.setMetaData(str.str());
306
    return &image;
307
  }
308
};
309
} // end of namespace icl
310
#endif
311

    
312

    
313

    
314

    
315
#ifdef ICL_SYSTEM_LINUX
316
#ifdef HAVE_VIDEODEV
317
#include <ICLIO/PWCGrabber.h>
318
#endif
319
#ifdef HAVE_VIDEODEV
320
#include <ICLIO/V4L2Grabber.h>
321
#endif
322

    
323
#endif
324

    
325
#ifdef HAVE_LIBDC
326
#include <ICLIO/DCGrabber.h>
327
#endif
328

    
329
#ifdef HAVE_UNICAP
330
#include <ICLIO/UnicapGrabber.h>
331
#endif
332

    
333
#ifdef HAVE_XCF
334
#include <ICLIO/XCFPublisherGrabber.h>
335
#include <ICLIO/XCFServerGrabber.h>
336
#include <ICLIO/XCFMemoryGrabber.h>
337
#endif
338

    
339
#ifdef HAVE_LIBMESASR
340
#include <ICLIO/SwissRangerGrabber.h>
341
#endif
342

    
343
#ifdef HAVE_MV
344
#include </MVGrabber.h>
345
#endif
346

    
347
#ifdef HAVE_XINE
348
#include <ICLIO/VideoGrabber.h>
349
#endif
350

    
351
#ifdef HAVE_OPENCV
352
#include <ICLIO/OpenCVCamGrabber.h>
353
#include <ICLIO/OpenCVVideoGrabber.h>
354
#endif
355

    
356
#ifdef HAVE_QT
357
#include <ICLIO/SharedMemoryGrabber.h>
358
#endif
359

    
360
#ifdef HAVE_LIBFREENECT
361
#include <ICLIO/KinectGrabber.h>
362
#endif
363

    
364
#ifdef HAVE_PYLON
365
#include <ICLIO/PylonGrabber.h>
366
#endif
367

    
368
#ifdef HAVE_OPENNI
369
#include <ICLIO/OpenNIGrabber.h>
370
#endif
371

    
372
#include <ICLIO/DemoGrabber.h>
373
#include <ICLUtils/Exception.h>
374

    
375
#include <ICLUtils/TextTable.h>
376

    
377

    
378
#if defined(HAVE_RSB) && defined(HAVE_PROTOBUF)
379
#include <ICLIO/RSBGrabber.h>
380
#endif
381

    
382
namespace icl{
383
  static std::vector<GrabberDeviceDescription> deviceList;
384

    
385

    
386
  GenericGrabber::GenericGrabber(const std::string &desiredAPIOrder,
387
                                 const std::string &params,
388
                                 bool notifyErrors) throw(ICLException):m_poGrabber(0){
389
    init(desiredAPIOrder,params,notifyErrors);
390
  }
391

    
392
  GenericGrabber::GenericGrabber(const ProgArg &pa) throw (ICLException):m_poGrabber(0){
393
    init(pa);
394
  }
395

    
396
  void GenericGrabber::init(const ProgArg &pa) throw (ICLException){
397
    init(*pa,(*pa) + "=" + *icl::pa(pa.getID(),1));
398
  }
399

    
400
  struct SpecifiedDevice{
401
    std::string type;
402
    std::string id;
403
    std::vector<std::string> options;
404
  };
405

    
406
  static std::pair<std::string,std::string> split_at_first(char c, const std::string &s){
407
    size_t pAt = s.find(c);
408
    if(pAt != std::string::npos){
409
      return std::pair<std::string,std::string>(s.substr(0,pAt), s.substr(pAt));
410
    }else{
411
      return std::pair<std::string,std::string>(s,"");
412
    }
413
  }
414

    
415
  typedef std::map<std::string,SpecifiedDevice> ParamMap;
416

    
417
  static ParamMap create_param_map(const std::string &filter){
418
    std::vector<std::string> ts = tok(filter,",");
419

    
420
    ParamMap pmap;
421

    
422
    static const char *plugins[] = { "pwc","dc","dc800","unicap","file","demo","create",
423
                                     "xcfp","xcfs","xcfm","mv","sr","xine","cvvideo",
424
                                     "cvcam","sm","kinectd","kinectc","kinecti",
425
                                     "pylon","rsb","surface"};
426
    static const int NUM_PLUGINS=sizeof(plugins)/sizeof(char*);
427

    
428
    for(unsigned int i=0;i<ts.size();++i){
429
      std::pair<std::string,std::string> tsi = split_at_first('@',ts[i]);
430

    
431
      std::vector<std::string> ab = tok(tsi.first,"=");
432
      //SHOW(ab[0]);
433
      //if(ab.size() > 1) SHOW(ab[1]);
434

    
435
      unsigned int S = ab.size();
436
      switch(S){
437
        case 1: case 2:
438
          if(std::find(plugins, plugins+NUM_PLUGINS, ab[0])){
439
            //std::pair<std::string,std::string> p = S==2 ? split_options(ab[1]) : std::pair<std::string,std::string>("","");
440
            SpecifiedDevice s = { ab[0], (S==2 ? ab[1] : std::string("")), tok(tsi.second,"@") };
441
            pmap[ab[0]] = s;
442
            //DEBUG_LOG("setting pmap[" << ab[0] << "] to '" << (pmap[ab[0]])<< '\'');
443
          }else{
444
            ERROR_LOG("GenericGrabber: unsupported device: ["<< ab[0] << "] (skipping)");
445
          }
446
          break;
447
        default:
448
          ERROR_LOG("GenericGrabber: invalid device filter token: [" << ts[i] << "] (skipping)");
449
      }
450
    }
451
    return pmap;
452
  }
453

    
454
#if HAVE_UNICAP
455
  static bool is_int(const std::string &x){
456
    int i = parse<int>(x);
457
    return i>0 || x=="0";
458
  }
459
#endif
460

    
461
  void GenericGrabber::init(const std::string &desiredAPIOrder,
462
                                 const std::string &params,
463
                                 bool notifyErrors) throw(ICLException){
464
    Mutex::Locker __lock(m_mutex);
465
    ICL_DELETE(m_poGrabber);
466
    m_sType = "";
467

    
468
    ParamMap pmap = create_param_map(params);
469

    
470
    std::string errStr;
471

    
472
#define ADD_ERR(P) errStr += errStr.size() ? std::string(",") : ""; \
473
                   errStr += std::string(P)+"("+pmap[P].id+")"
474

    
475
    std::vector<std::string> l = tok(desiredAPIOrder,",");
476
    for(unsigned int i=0;i<l.size();++i){
477

    
478
      const bool createListOnly = (l[i] == "list");
479
      std::vector<std::string> supportedDevices;
480

    
481
#ifdef USE_CRAZY_SURFACE_GRABBER
482
      if(createListOnly){
483
  supportedDevices.push_back("surface:dummy:Microsoft surface camera source");
484
      }
485
      if(l[i] == "surface"){
486
  try{
487
    SurfaceGrabber *grabber = new SurfaceGrabber;
488
    m_poGrabber = grabber;
489
    m_sType = "surface";
490
  }catch(ICLException &e){
491
    ADD_ERR(l[i]);
492
  }
493

    
494
      }
495

    
496
#endif
497

    
498
#ifdef HAVE_LIBFREENECT
499
      if(createListOnly){
500
        supportedDevices.push_back("kinectd:device ID:kinect depth camera source:");
501
        supportedDevices.push_back("kinectc:device ID:kinect color camera source");
502
        supportedDevices.push_back("kinecti:devide ID:kinect IR camera source");
503
      }
504
      if(l[i] == "kinectd" || l[i] == "kinectc" || l[i] == "kinecti"){
505
        KinectGrabber::Mode mode = KinectGrabber::GRAB_DEPTH_IMAGE;
506
        switch(l[i][6]){
507
          case 'd': mode = KinectGrabber::GRAB_DEPTH_IMAGE; break;
508
          case 'c': mode = KinectGrabber::GRAB_RGB_IMAGE; break;
509
          case 'i': mode = KinectGrabber::GRAB_IR_IMAGE_8BIT; break;
510
          default: break;
511
        }
512
        try{
513
          // new KinectGrabber *kin = new KinectGrabber(format,to32s(pmap[l[i]]));
514
          KinectGrabber *kin = new KinectGrabber(mode,to32s(pmap[l[i]].id));
515
          m_poGrabber = kin;
516
          m_sType = l[i];
517
          break;
518
        }catch(...){
519
          ADD_ERR(l[i]);
520
          continue;
521
        }
522
      }
523

    
524
#endif
525

    
526

    
527

    
528
#ifdef HAVE_VIDEODEV
529
      if(createListOnly){
530
        supportedDevices.push_back("pwc:/dev/videoX index:Phillip 640 Webcam source");
531
        supportedDevices.push_back("v4l2:/dev/videoX index or device-file:V4l2 based camera source");
532
      }
533
      if(l[i] == "pwc"){
534
        PWCGrabber *pwc = new PWCGrabber;
535
        if(pwc->init(Size(640,480),24,to32s(pmap["pwc"].id),true)){
536
          m_poGrabber = pwc;
537
          m_sType = "pwc";
538
          break;
539
        }else{
540
          ADD_ERR("pwc");
541
          delete pwc;
542
          continue;
543
        }
544
      }
545

    
546
      if(l[i] == "v4l2"){
547
        try{
548
          V4L2Grabber *g = new V4L2Grabber(pmap["v4l2"].id);
549
          m_poGrabber = g;
550
          m_sType = "v4l2";
551
          break;
552
        }catch(ICLException &ex){
553
          ADD_ERR("v4l2 [error message:" + str(ex.what()) + "]");
554
          continue;
555
        }
556
      }
557
#endif
558

    
559
#ifdef HAVE_LIBDC
560
      if(createListOnly){
561
        supportedDevices.push_back("dc:camera ID or unique ID:IEEE-1394a based camera source (FireWire 400)");
562
        supportedDevices.push_back("dc:camera ID or unique ID:IEEE-1394b based camera source (FireWire 800)");
563
      }
564
      if(l[i] == "dc" || l[i] == "dc800"){
565
        std::vector<DCDevice> devs = DCGrabber::getDCDeviceList(false);
566

    
567

    
568
        //        int idx = (l[i]=="dc") ? to32s(pmap["dc"]) : to32s(pmap["dc800"]);
569
        std::string d =  (l[i]=="dc") ? pmap["dc"].id : pmap["dc800"].id;
570
        if(!d.length()) throw ICLException("GenericGrabber::init: got dc[800] with empty sub-arg!");
571
        std::vector<std::string> ts = tok(d,"|||",false);
572
        if(ts.size() > 1){
573
          // we take the first one here, because usually no one defines both ...
574
          d = ts[0];
575
        }
576

    
577
        int index = -1;
578
        std::string uniqueID;
579
        if(d.size() < 4){
580
          //"0-999" -> very short string -> this is an index then
581
          index = to32s(d);
582
        }else{
583
          //"something very long" -> this is a unique ID then
584
          uniqueID = d;
585
        }
586

    
587
        if(index < 0){
588
          for(unsigned int j=0;j<devs.size();++j){
589
            if(devs[j].getUniqueStringIdentifier() == uniqueID){
590
              m_poGrabber = new DCGrabber(devs[j],l[i]=="dc"?400:800);
591
              m_sType = l[i];
592
              break;
593
            }
594
          }
595
          if(!m_poGrabber){
596
            if(l[i]=="dc"){
597
              ADD_ERR("dc");
598
            }else{
599
              ADD_ERR("dc800");
600
            }
601
            continue;
602
          }
603
        }else{
604
          if(index >= (int)devs.size()){
605
            if(l[i]=="dc"){
606
              ADD_ERR("dc");
607
            }else{
608
              ADD_ERR("dc800");
609
            }
610
            continue;
611
          }else{
612
            m_poGrabber = new DCGrabber(devs[index], l[i]=="dc"?400:800);
613
            m_sType = l[i];
614
            break;
615
          }
616
        }
617
      }
618
#endif
619

    
620
#ifdef HAVE_LIBMESASR
621
      if(createListOnly){
622
        supportedDevices.push_back("sr:device Index or -1 for auto select:Mesa Imaging SwissRanger depth camera source");
623
      }
624

    
625
      if(l[i] == "sr"){
626
        std::vector<std::string> srts = tok(pmap["sr"].id,"c");
627
        int device = 0;
628
        int channel = -1;
629
        m_sType = "sr";
630
        if(srts.size() > 1){
631
          device = to32s(srts[0]);
632
          channel = to32s(srts[1]);
633
        }else{
634
          device = to32s(srts[0]);
635
        }
636

    
637
        try{
638
          m_poGrabber = new SwissRangerGrabber(device,depth32f,channel);
639
        }catch(ICLException &e){
640
          ADD_ERR("sr");
641
          errStr += "[error message: " + str(e.what()) + "]";
642
          continue;
643
        }
644
        break;
645
      }
646
#endif
647

    
648
#ifdef HAVE_XINE
649
      if(createListOnly){
650
        supportedDevices.push_back("xine:video filename:Xine library based video file source");
651
      }
652

    
653
      if(l[i] == "xine"){
654
        try{
655
          m_poGrabber = new VideoGrabber(pmap["xine"].id);
656
          m_sType = "xine";
657
        }catch(ICLException &e){
658
          ADD_ERR("xine");
659
          continue;
660
        }
661
        break;
662
      }
663
#endif
664

    
665
#ifdef HAVE_UNICAP
666
      if(createListOnly){
667
        supportedDevices.push_back("unicap:camera ID or pattern:Unicap library based camera source");
668
      }
669

    
670
      if(l[i] == "unicap"){
671
        std::vector<UnicapDevice> devs;
672
        if(is_int(pmap["unicap"].id)){
673
          devs = UnicapGrabber::getUnicapDeviceList("");
674
          int idx = parse<int>(pmap["unicap"].id);
675
          if((int)devs.size() > idx){
676
            m_poGrabber = new UnicapGrabber(devs[idx]);
677
            m_sType = "unicap";
678
            break;
679
          }else{
680
            ADD_ERR("unicap");
681
            continue;
682
          }
683
        }else{
684
          devs = UnicapGrabber::getUnicapDeviceList(pmap["unicap"].id);
685
          if(!devs.size()){
686
            ADD_ERR("unicap");
687
            continue;
688
          }else{
689
            m_poGrabber = new UnicapGrabber(devs[0]);
690
            m_sType = "unicap";
691
            break;
692
          }
693
        }
694
      }
695
#endif
696

    
697

    
698
#ifdef HAVE_XCF
699
      if(createListOnly){
700
        supportedDevices.push_back("xcfs:xcf server stream name:XCF-based server network source");
701
        supportedDevices.push_back("xcfp:xcf publisher stream name:XCF-based publisher network source");
702
        supportedDevices.push_back("xcfm:xcf Active-Memory name:XCF-based ActiveMemory network source");
703
      }
704
      if(l[i].size()==4 && l[i].substr(0,3) == "xcf"){
705
        switch(l[i][3]){
706
          case 's':
707
            try{
708
              m_poGrabber = new XCFServerGrabber(pmap["xcfs"].id);
709
            }catch(...){
710
              if(notifyErrors){
711
                m_poGrabber = 0;
712
                ADD_ERR("xcfs");
713
              }
714
            }
715
            break;
716
          case 'p':
717
            try{
718
              m_poGrabber = new XCFPublisherGrabber(pmap["xcfp"].id);
719
            }catch(...){
720
              if(notifyErrors){
721
                m_poGrabber = 0;
722
                ADD_ERR("xcfp");
723
              }
724
            }
725
            break;
726
          case 'm':
727
            try{
728
              m_poGrabber = new XCFMemoryGrabber(pmap["xcfm"].id);
729
            }catch(...){
730
              if(notifyErrors){
731
                m_poGrabber = 0;
732
                ADD_ERR("xcfm");
733
              }
734
            }
735
            break;
736
          default:
737
            break;
738
        }
739
        if(m_poGrabber){
740
          m_sType = l[i];
741
          break;
742
        }else{
743
          continue;
744
        }
745
      }
746
#endif
747

    
748
#ifdef HAVE_MV
749
      if(createListOnly){
750
        supportedDevices.push_back("mv:camera ID:MatrixVision driver based camera source");
751
      }
752
      // not yet supported, and maybe, already replaced by pylon grabber?
753
      if(l[i] == "mv") {
754
        std::vector<MVDevice> devs = MVGrabber::getDeviceList();
755

    
756
        if(!devs.size()) {
757
          ADD_ERR("mv");
758
          continue;
759
        } else {
760
          m_poGrabber = new MVGrabber(pmap["mv"].id);
761
          m_sType = "mv";
762
          break;
763
        }
764
      }
765
#endif
766

    
767

    
768
#ifdef HAVE_OPENCV
769
      if(createListOnly){
770
        supportedDevices.push_back("cvvideo:video filename:OpenCV based video file source");
771
        supportedDevices.push_back("cvcam:camera ID:OpenCV based camera source");
772
      }
773

    
774
      if(l[i] == "cvvideo") {
775
        try{
776
          m_poGrabber = new OpenCVVideoGrabber(pmap["cvvideo"].id);
777
          m_sType = "cvvideo";
778
          break;
779
        }catch(ICLException &e){
780
          ADD_ERR("cvvideo");
781
          continue;
782
        }
783
      }
784
      if(l[i] == "cvcam") {
785
        try{
786
          m_poGrabber = new OpenCVCamGrabber(to32s(pmap["cvcam"].id));
787
          m_sType = "cvcam";
788
          break;
789
        }catch(ICLException &e){
790
          ADD_ERR("cvcam");
791
          continue;
792
        }
793
      }
794
#endif
795

    
796
#ifdef HAVE_QT
797
      if(createListOnly){
798
        supportedDevices.push_back("sm:shared memory segment name:Qt-based shared memory source");
799
      }
800

    
801
      if(l[i] == "sm") {
802
        try{
803
          m_poGrabber = new SharedMemoryGrabber(pmap["sm"].id);
804
          m_sType = "sm";
805
          break;
806
        }catch(ICLException &e){
807
          ADD_ERR("sm");
808
          continue;
809
        }
810
      }
811
#endif
812

    
813
#ifdef HAVE_PYLON
814
      if(createListOnly){
815
        supportedDevices.push_back("pylon:camera ID ?? or IP-address:Basler Pylon based gigabit-ethernet (GIG-E) camera source");
816
      }
817

    
818
      if(l[i] == "pylon"){
819
        if (pmap["pylon"].id == "-help"){
820
          pylon::PylonGrabber::printHelp();
821
          ADD_ERR("pylon");
822
          continue;
823
        }
824
        try{
825
          m_poGrabber = new pylon::PylonGrabber(pmap["pylon"].id);
826
          m_sType = "pylon";
827
          break;
828
        } catch (ICLException &e){
829
          ADD_ERR("pylon");
830
          continue;
831
        }
832
      }
833
#endif
834

    
835
#ifdef HAVE_OPENNI
836
      if(createListOnly){
837
        supportedDevices.push_back("oni:camera ID");
838
      }
839

    
840
      if(l[i] == "oni"){
841
        try{
842
          m_poGrabber = new OpenNIGrabber(pmap["oni"].id);
843
          m_sType = "oni";
844
          break;
845
        } catch (ICLException &e){
846
          ADD_ERR("oni");
847
          continue;
848
        }
849
      }
850
#endif
851

    
852
#if defined(HAVE_RSB) && defined(HAVE_PROTOBUF)
853
      if(createListOnly){
854
        supportedDevices.push_back("rsb:[comma sep. transport list=spread]\\:scope:Robotics Service Bus based image source");
855
      }
856
      if(l[i] == "rsb"){
857

    
858
        try{
859
          std::vector<std::string> ts = tok(pmap["rsb"].id,":");
860
          if(!ts.size()) throw ICLException("invalid argument count (expected 1 or 2)");
861
          else if(ts.size() == 1) m_poGrabber = new RSBGrabber(ts[0]);
862
          else if(ts.size() == 2){
863
            m_poGrabber = new RSBGrabber(ts[1],ts[0]);
864
          }else{
865
            throw ICLException("invalid definition string (exptected: [transport-list]:scope");
866
          }
867
          m_sType = "rsb";
868
          break;
869
        }catch(std::exception &e){
870
          ADD_ERR("rsb");
871
          continue;
872
        }
873
      }
874
#endif
875

    
876
      if(createListOnly){
877
        supportedDevices.push_back("file:file name or file-pattern (in ''):image source for single or a list of image files");
878
        supportedDevices.push_back("demo:0:demo image source");
879
        supportedDevices.push_back("create:parrot|lena|cameraman|mandril:everywhere available test images source");
880
      }
881

    
882
      if(l[i] == "file"){
883

    
884
        try{
885
          if(FileList(pmap["file"].id).size()){
886
            m_sType = "file";
887
            m_poGrabber = new FileGrabber(pmap["file"].id);
888
            break;
889
          }else{
890
            ADD_ERR("file");
891
            continue;
892
          }
893
        }catch(icl::FileNotFoundException &ex){
894
          ADD_ERR("file");
895
          continue;
896
        }
897
      }
898
      if(l[i] == "demo"){
899
        m_poGrabber = new DemoGrabber(to32f(pmap["demo"].id));
900
        m_sType = "demo";
901
      }
902

    
903
      if(l[i] == "create"){
904
        m_poGrabber = new CreateGrabber(pmap["create"].id);
905
        m_sType = "create";
906
      }
907

    
908

    
909
      if(createListOnly){
910
        std::cout << "the following generic grabber plugins are available:" << std::endl;
911

    
912
        TextTable t(4,supportedDevices.size()+1,80);
913
        t[0] = tok("index,ID,parameter,description",",");
914
        for(size_t k=0;k<supportedDevices.size();++k){
915
          t[k+1] = tok(str(k)+":"+supportedDevices[k],":",true,'\\');
916
        }
917
        std::cout << t << std::endl;
918
        std::terminate();
919
      }
920
    }
921
    if(!m_poGrabber && notifyErrors){
922
      std::string errMsg("generic grabber was not able to find any suitable device\ntried:");
923
      throw ICLException(errMsg+errStr);
924
    }else{
925
      GrabberDeviceDescription d(m_sType,pmap[m_sType].id,"any device");
926

    
927
      for(unsigned int i=0;i<deviceList.size();++i){
928
        if(deviceList[i].type == d.type && deviceList[i].id == d.id) return;
929
      }
930
      deviceList.push_back(d);
931

    
932

    
933
      const std::vector<std::string> &options = pmap[m_sType].options;
934
      /// setting extra properties ...
935
      for(unsigned int i=0;i<options.size();++i){
936
        std::pair<std::string,std::string> p = split_at_first('=',options[i]);
937
        if(p.second.length()) p.second = p.second.substr(1);
938
        if(p.first == "load"){
939
          m_poGrabber->loadProperties(p.second);
940
        }else if(p.first == "info"){
941
          std::cout << "Property list for " << d << std::endl;
942
          std::vector<std::string> ps = m_poGrabber->getPropertyList();
943
          TextTable t(4,ps.size()+1,35);
944
          t[0] = tok("property,type,allowed values,current value",",");
945
          for(unsigned int j=0;j<ps.size();++j){
946
            const std::string &p2 = ps[j];
947
            const std::string ty = m_poGrabber->getType(p2);
948
            const bool isCommand = ty == "command";
949
            const bool isInfo = ty == "info";
950

    
951
            t(0,j+1) = p2;
952
            t(1,j+1) = ty;
953
            t(2,j+1) = (isInfo||isCommand) ? str("-") : m_poGrabber->getInfo(p2);
954
            t(3,j+1) = isCommand ? "-" : m_poGrabber->getValue(p2);
955
          }
956
          std::cout << t << std::endl;
957
          std::terminate();
958
        }else if(p.first == "udist"){
959
          this->enableUndistortion(p.second);
960
        }else{
961
          //  DEBUG_LOG("setting property -" << p.first << "- to value -" << p.second << "-");
962
          m_poGrabber->setProperty(p.first,p.second);
963
        }
964
      }
965
    }
966
  }
967

    
968
  void GenericGrabber::resetBus(const std::string &deviceList, bool verbose){
969
    std::vector<std::string> ts = tok(deviceList,",");
970

    
971
    for(unsigned int i=0;i<ts.size();++i){
972
      const std::string &t = ts[i];
973
      (void)t; // to avoid warnings in case of no dc support
974
#ifdef HAVE_LIBDC
975
      if(t == "dc" || t == "dc800"){
976
        DCGrabber::dc1394_reset_bus(verbose);
977
      }
978
#endif
979
#ifdef HAVE_QT
980
      if( t == "sm" ){
981
        SharedMemoryGrabber::resetBus();
982
      }
983
#endif
984
      // others are not supported yet
985
    }
986

    
987
  }
988

    
989
  template<class T>
990
  static inline bool contains(const std::map<std::string,T> &m,const std::string &t){
991
      return m.find(t) != m.end();
992
  }
993

    
994
  static const GrabberDeviceDescription *find_description(const std::vector<GrabberDeviceDescription> &ds, const std::string &id){
995
    for(unsigned int i=0;i<ds.size();++i){
996
      std::vector<std::string> ts = tok(ds[i].id,"|||",false);
997
      if(std::find(ts.begin(),ts.end(),id) != ts.end()){
998
        return &ds[i];
999
      }
1000
    }
1001
    return 0;
1002
  }
1003
#ifdef HAVE_LIBFREENECT
1004
  static const GrabberDeviceDescription *find_description_2(const std::vector<GrabberDeviceDescription> &ds, const std::string &id,
1005
                                                            const std::string &type){
1006
    for(unsigned int i=0;i<ds.size();++i){
1007
      if(ds[i].type != type) continue; // in case of kinect[i|c|d], we have several fitting devices here
1008
      std::vector<std::string> ts = tok(ds[i].id,"|||",false);
1009
      if(std::find(ts.begin(),ts.end(),id) != ts.end()){
1010
        return &ds[i];
1011
      }
1012
    }
1013
    return 0;
1014
  }
1015
#endif
1016

    
1017
  template<class T>
1018
  static void add_devices(std::vector<GrabberDeviceDescription> &all,
1019
                          const std::string &dev,
1020
                          bool useFilter,
1021
                          ParamMap &pmap){
1022

    
1023
    if(!useFilter || contains(pmap,dev)){
1024
      std::vector<GrabberDeviceDescription> ds = T::getDeviceList(true);
1025
      if(dev.length() >= 2 && dev[0] == 'd' && dev[1] == 'c'){ // dirty hack for dc devices
1026
        bool kick800 = dev.length()==2;
1027
        std::vector<GrabberDeviceDescription> newds;
1028
        for(unsigned int i=0;i<ds.size();++i){
1029
          if(kick800 && ds[i].type != "dc800") newds.push_back(ds[i]);
1030
          if(!kick800 && ds[i].type != "dc") newds.push_back(ds[i]);
1031
        }
1032
        ds = newds;
1033
      }
1034

    
1035
      if(useFilter && pmap[dev].id.length()){
1036
        const GrabberDeviceDescription *d = find_description(ds,pmap[dev].id);
1037
        if(d){
1038
          all.push_back(*d);
1039
        }
1040
      }else{
1041
        std::copy(ds.begin(),ds.end(),std::back_inserter(all));
1042
      }
1043
    }
1044
  }
1045

    
1046
#ifdef HAVE_LIBFREENECT
1047
  template<>
1048
  void add_devices<KinectGrabber>(std::vector<GrabberDeviceDescription> &all,
1049
                                  const std::string &dev,
1050
                                  bool useFilter,
1051
                                  ParamMap &pmap){
1052
    if(!useFilter || contains(pmap,"kinectd") || contains(pmap,"kinectc") || contains(pmap,"kinecti")){
1053
      std::vector<GrabberDeviceDescription> ds = KinectGrabber::getDeviceList(true);
1054
      if(useFilter && (pmap["kinectd"].id.length() || pmap["kinectc"].id.length() || pmap["kinecti"].id.length())){
1055
        if(pmap["kinectd"].id.length()){
1056
          const GrabberDeviceDescription *d = find_description_2(ds,pmap["kinectd"].id,"kinectd");
1057
          if(d){
1058
            all.push_back(*d);
1059
          }
1060
        }
1061
        if(pmap["kinectc"].id.length()){
1062

    
1063
          const GrabberDeviceDescription *d = find_description_2(ds,pmap["kinectc"].id,"kinectc");
1064
          if(d){
1065
            all.push_back(*d);
1066
          }
1067
        }
1068
        if(pmap["kinecti"].id.length()){
1069
          const GrabberDeviceDescription *d = find_description_2(ds,pmap["kinecti"].id,"kinecti");
1070
          if(d){
1071
            all.push_back(*d);
1072
          }
1073
        }
1074
      }else{
1075
        std::copy(ds.begin(),ds.end(),std::back_inserter(all));
1076
      }
1077
    }
1078
  }
1079
#endif
1080

    
1081
  const std::vector<GrabberDeviceDescription> &GenericGrabber::getDeviceList(const std::string &filter, bool rescan){
1082

    
1083
    if(rescan){
1084
      deviceList.clear();
1085
      bool useFilter = filter.length();
1086
      ParamMap pmap;
1087
      if(useFilter){
1088
        pmap = create_param_map(filter);
1089
      }
1090

    
1091
      if(useFilter && pmap.find("demo") != pmap.end()){
1092
        deviceList.push_back(GrabberDeviceDescription("demo","0","Demo Grabber Device"));
1093
      }
1094

    
1095
#ifdef HAVE_VIDEODEV
1096
      add_devices<PWCGrabber>(deviceList,"pwc",useFilter,pmap);
1097
      add_devices<V4L2Grabber>(deviceList,"v4l2",useFilter,pmap);
1098
#endif
1099

    
1100
#ifdef HAVE_LIBDC
1101
      add_devices<DCGrabber>(deviceList,"dc",useFilter,pmap);
1102
      add_devices<DCGrabber>(deviceList,"dc800",useFilter,pmap);
1103
#endif
1104

    
1105
#ifdef HAVE_UNICAP
1106
      add_devices<UnicapGrabber>(deviceList,"unicap",useFilter,pmap);
1107
#endif
1108

    
1109

    
1110
#ifdef HAVE_LIBMESASR
1111
      add_devices<SwissRangerGrabber>(deviceList,"sr",useFilter,pmap);
1112
#endif
1113

    
1114
#ifdef HAVE_OPENCV
1115
      add_devices<OpenCVCamGrabber>(deviceList,"cvcam",useFilter,pmap);
1116
#endif
1117

    
1118

    
1119
#ifdef HAVE_QT
1120
      add_devices<SharedMemoryGrabber>(deviceList,"sm",useFilter,pmap);
1121
#endif
1122

    
1123
#ifdef HAVE_LIBFREENECT
1124
      add_devices<KinectGrabber>(deviceList,"",useFilter,pmap);
1125
#endif
1126

    
1127
#ifdef HAVE_PYLON
1128
      add_devices<pylon::PylonGrabber>(deviceList,"pylon",useFilter,pmap);
1129
#endif
1130

    
1131
#ifdef HAVE_OPENNI
1132
      add_devices<OpenNIGrabber>(deviceList,"oni",useFilter,pmap);
1133
#endif
1134

    
1135
#if defined(HAVE_RSB) && defined(HAVE_PROTOBUF)
1136
      add_devices<RSBGrabber>(deviceList,"rsb",useFilter,pmap);
1137
#endif
1138
    }
1139
    return deviceList;
1140
  }
1141
}