v4l2-ruby 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/v4l2/v4l2.c ADDED
@@ -0,0 +1,967 @@
1
+ /*
2
+ * Video 4 Linux V2 for Ruby interface library.
3
+ *
4
+ * Copyright (C) 2015 Hiroshi Kuwagata. All rights reserved.
5
+ */
6
+
7
+ /*
8
+ * $Id: v4l2.c 121 2016-11-18 04:32:27Z pi $
9
+ */
10
+
11
+ #include "ruby.h"
12
+ #include "ruby/encoding.h"
13
+
14
+ #include "camera.h"
15
+
16
+ #define N(x) (sizeof((x))/sizeof(*(x)))
17
+
18
+ extern rb_encoding* rb_utf8_encoding(void);
19
+
20
+ static VALUE module;
21
+ static VALUE camera_klass;
22
+ static VALUE control_klass;
23
+ static VALUE integer_klass;
24
+ static VALUE boolean_klass;
25
+ static VALUE menu_klass;
26
+ //static VALUE imenu_klass;
27
+ static VALUE menu_item_klass;
28
+ static VALUE frame_cap_klass;
29
+ static VALUE fmt_desc_klass;
30
+
31
+ static ID id_yuyv;
32
+ static ID id_yuv422;
33
+ static ID id_nv21;
34
+ static ID id_nv12;
35
+ static ID id_nv16;
36
+ static ID id_rgb565;
37
+ static ID id_mjpeg;
38
+ static ID id_h264;
39
+ static ID id_iv_name;
40
+ static ID id_iv_driver;
41
+ static ID id_iv_bus;
42
+ static ID id_iv_id;
43
+ static ID id_iv_max;
44
+ static ID id_iv_min;
45
+ static ID id_iv_step;
46
+ static ID id_iv_default;
47
+ static ID id_iv_items;
48
+ static ID id_iv_index;
49
+ static ID id_iv_width;
50
+ static ID id_iv_height;
51
+ static ID id_iv_rate;
52
+ static ID id_iv_fcc;
53
+ static ID id_iv_desc;
54
+
55
+ static void
56
+ rb_camera_free(void* ptr)
57
+ {
58
+ if (((camera_t*)ptr)->state != 6) {
59
+ camera_finalize( ptr);
60
+ }
61
+
62
+ free( ptr);
63
+ }
64
+
65
+ static VALUE
66
+ rb_camera_alloc(VALUE self)
67
+ {
68
+ camera_t* ptr;
69
+
70
+ return Data_Make_Struct(camera_klass, camera_t, 0, rb_camera_free, ptr);
71
+ }
72
+
73
+ static VALUE
74
+ rb_camera_open(VALUE self, VALUE device)
75
+ {
76
+ VALUE ret;
77
+
78
+ ret = rb_obj_alloc(camera_klass);
79
+ rb_obj_call_init(ret, 1, &device);
80
+
81
+ return ret;
82
+ }
83
+
84
+ static VALUE
85
+ rb_camera_initialize(VALUE self, VALUE dev)
86
+ {
87
+ int err;
88
+ camera_t* ptr;
89
+
90
+ /*
91
+ * argument check
92
+ */
93
+ Check_Type(dev, T_STRING);
94
+
95
+ /*
96
+ * strip object
97
+ */
98
+ Data_Get_Struct(self, camera_t, ptr);
99
+
100
+ /*
101
+ * initialize struct
102
+ */
103
+ err = camera_initialize(ptr, RSTRING_PTR(dev));
104
+ if (err) {
105
+ rb_raise(rb_eRuntimeError, "initialize camera context failed.");
106
+ }
107
+
108
+ /*
109
+ * set default instance variable
110
+ */
111
+ rb_ivar_set(self, id_iv_name,
112
+ rb_enc_str_new_cstr(ptr->name, rb_utf8_encoding()));
113
+ rb_ivar_set(self, id_iv_driver,
114
+ rb_enc_str_new_cstr(ptr->driver, rb_utf8_encoding()));
115
+ rb_ivar_set(self, id_iv_bus,
116
+ rb_enc_str_new_cstr(ptr->bus, rb_utf8_encoding()));
117
+
118
+ return Qtrue;
119
+ }
120
+
121
+ static VALUE
122
+ rb_camera_close( VALUE self)
123
+ {
124
+ int err;
125
+ camera_t* ptr;
126
+
127
+ /*
128
+ * strip object
129
+ */
130
+ Data_Get_Struct(self, camera_t, ptr);
131
+
132
+ /*
133
+ * convert
134
+ */
135
+ err = camera_finalize(ptr);
136
+ if (err) {
137
+ rb_raise(rb_eRuntimeError, "finalize camera context failed.");
138
+ }
139
+
140
+ return Qnil;
141
+ }
142
+
143
+ static VALUE
144
+ get_menu_list(camera_t* ptr, int ctrl, int min, int max)
145
+ {
146
+ VALUE ret;
147
+ int i;
148
+ int err;
149
+ struct v4l2_querymenu item;
150
+
151
+ ret = rb_ary_new();
152
+ for (i = min; i <= max; i++) {
153
+ err = camera_get_menu_item(ptr, ctrl, i, &item);
154
+ if (!err) {
155
+ VALUE tmp;
156
+
157
+ tmp = rb_obj_alloc(menu_item_klass);
158
+ rb_ivar_set(tmp, id_iv_name, rb_str_new2((const char*)item.name));
159
+ rb_ivar_set(tmp, id_iv_index, INT2FIX(item.index));
160
+
161
+ rb_ary_push(ret, tmp);
162
+ }
163
+ }
164
+
165
+ return ret;
166
+ }
167
+
168
+ static VALUE
169
+ get_int_menu_list(camera_t* ptr, int ctrl, int min, int max)
170
+ {
171
+ VALUE ret;
172
+ int i;
173
+ int err;
174
+ struct v4l2_querymenu item;
175
+
176
+ ret = rb_ary_new();
177
+ for (i = min; i <= max; i++) {
178
+ err = camera_get_menu_item(ptr, ctrl, i, &item);
179
+ if (!err) {
180
+ VALUE tmp;
181
+
182
+ tmp = rb_obj_alloc(menu_item_klass);
183
+ rb_ivar_set(tmp, id_iv_name, rb_sprintf("%lld", item.value));
184
+ rb_ivar_set(tmp, id_iv_index, INT2FIX(item.index));
185
+
186
+ rb_ary_push(ret, tmp);
187
+ }
188
+ }
189
+
190
+ return ret;
191
+ }
192
+
193
+ static VALUE
194
+ get_control_info(camera_t* ptr, int ctrl)
195
+ {
196
+ VALUE ret;
197
+ int err;
198
+ struct v4l2_queryctrl info;
199
+
200
+ ret = Qnil;
201
+ err = camera_get_control_info(ptr, ctrl, &info);
202
+ if (!err) {
203
+ switch (info.type) {
204
+ case V4L2_CTRL_TYPE_INTEGER:
205
+ ret = rb_obj_alloc(integer_klass);
206
+ rb_ivar_set(ret, id_iv_name, rb_str_new2((const char*)info.name));
207
+ rb_ivar_set(ret, id_iv_id, INT2NUM(info.id));
208
+ rb_ivar_set(ret, id_iv_min, INT2FIX(info.minimum));
209
+ rb_ivar_set(ret, id_iv_max, INT2FIX(info.maximum));
210
+ rb_ivar_set(ret, id_iv_step, INT2FIX(info.step));
211
+ rb_ivar_set(ret, id_iv_default, INT2FIX(info.default_value));
212
+ break;
213
+
214
+ case V4L2_CTRL_TYPE_BOOLEAN:
215
+ ret = rb_obj_alloc(boolean_klass);
216
+ rb_ivar_set(ret, id_iv_name, rb_str_new2((const char*)info.name));
217
+ rb_ivar_set(ret, id_iv_id, INT2NUM(info.id));
218
+ rb_ivar_set(ret, id_iv_default, (info.default_value)? Qtrue: Qfalse);
219
+ break;
220
+
221
+ case V4L2_CTRL_TYPE_MENU:
222
+ ret = rb_obj_alloc(menu_klass);
223
+ rb_ivar_set(ret, id_iv_name, rb_str_new2((const char*)info.name));
224
+ rb_ivar_set(ret, id_iv_id, INT2NUM(info.id));
225
+ rb_ivar_set(ret, id_iv_default, INT2FIX(info.default_value));
226
+ rb_ivar_set(ret, id_iv_items,
227
+ get_menu_list(ptr, ctrl, info.minimum, info.maximum));
228
+ break;
229
+
230
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
231
+ ret = rb_obj_alloc(menu_klass);
232
+ rb_ivar_set(ret, id_iv_name, rb_str_new2((const char*)info.name));
233
+ rb_ivar_set(ret, id_iv_id, INT2NUM(info.id));
234
+ rb_ivar_set(ret, id_iv_default, INT2FIX(info.default_value));
235
+ rb_ivar_set(ret, id_iv_items,
236
+ get_int_menu_list(ptr, ctrl, info.minimum, info.maximum));
237
+ break;
238
+
239
+ default:
240
+ fprintf(stderr, "unsupported type %d, name: %s\n",
241
+ info.type, info.name);
242
+ break;
243
+ }
244
+ }
245
+
246
+ return ret;
247
+ }
248
+
249
+ static VALUE
250
+ rb_camera_get_controls(VALUE self)
251
+ {
252
+ VALUE ret;
253
+ camera_t* ptr;
254
+ int i;
255
+ VALUE info;
256
+
257
+ Data_Get_Struct(self, camera_t, ptr);
258
+
259
+ ret = rb_ary_new();
260
+
261
+ for (i = 0; i < 43; i++) {
262
+ info = get_control_info(ptr, V4L2_CID_BASE + i);
263
+ if (info != Qnil) rb_ary_push(ret, info);
264
+ }
265
+
266
+ for (i = 0; i < 30; i++) {
267
+ info = get_control_info(ptr, V4L2_CID_CAMERA_CLASS_BASE + i);
268
+ if (info != Qnil) rb_ary_push(ret, info);
269
+ }
270
+
271
+ for (i = 0; i < 20; i++) {
272
+ info = get_control_info(ptr, V4L2_CID_JPEG_CLASS_BASE + i);
273
+ if (info != Qnil) rb_ary_push(ret, info);
274
+ }
275
+
276
+ return ret;
277
+ }
278
+
279
+ static VALUE
280
+ get_framerate_list(camera_t* cam, struct v4l2_frmsize_discrete* size)
281
+ {
282
+ VALUE ret;
283
+ int i;
284
+
285
+ int err;
286
+ struct v4l2_frmivalenum intval;
287
+ VALUE rate;
288
+
289
+ ret = rb_ary_new();
290
+
291
+ for (i = 0; ; i++) {
292
+ err = camera_get_frame_rate(cam, V4L2_PIX_FMT_MJPEG,
293
+ size->width, size->height, i, &intval);
294
+ if (err) break;
295
+
296
+ if (intval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
297
+ rate = rb_rational_new(INT2FIX(intval.discrete.denominator),
298
+ INT2FIX(intval.discrete.numerator));
299
+
300
+ rb_ary_push(ret, rate);
301
+ }
302
+ }
303
+
304
+ return ret;
305
+ }
306
+
307
+ static uint32_t
308
+ to_pixfmt(VALUE fmt)
309
+ {
310
+ uint32_t ret;
311
+ ID sym;
312
+
313
+ sym = rb_to_id(fmt);
314
+
315
+ if (sym == id_yuyv || sym == id_yuv422) {
316
+ ret = V4L2_PIX_FMT_YUYV;
317
+
318
+ } else if (sym == id_nv12) {
319
+ ret = V4L2_PIX_FMT_NV12;
320
+
321
+ } else if (sym == id_nv21) {
322
+ ret = V4L2_PIX_FMT_NV21;
323
+
324
+ } else if (sym == id_nv16) {
325
+ ret = V4L2_PIX_FMT_NV16;
326
+
327
+ } else if (sym == id_rgb565) {
328
+ ret = V4L2_PIX_FMT_RGB565;
329
+
330
+ } else if (sym == id_mjpeg) {
331
+ ret = V4L2_PIX_FMT_MJPEG;
332
+
333
+ } else if (sym == id_h264) {
334
+ ret = V4L2_PIX_FMT_H264;
335
+
336
+ } else {
337
+ rb_raise(rb_eRuntimeError, "Unsupported pixel format.");
338
+ }
339
+
340
+ return ret;
341
+ }
342
+
343
+ static VALUE
344
+ rb_camera_get_support_formats(VALUE self)
345
+ {
346
+ VALUE ret;
347
+ camera_t* ptr;
348
+
349
+ int i;
350
+ int err;
351
+ struct v4l2_fmtdesc desc;
352
+
353
+ VALUE fmt;
354
+ VALUE fcc;
355
+
356
+ Data_Get_Struct(self, camera_t, ptr);
357
+
358
+ ret = rb_ary_new();
359
+
360
+ for (i = 0; ;i++) {
361
+ err = camera_get_format_desc(ptr, i, &desc);
362
+ if (err) break;
363
+
364
+ fmt = rb_obj_alloc(fmt_desc_klass);
365
+ fcc = rb_sprintf("%c%c%c%c",
366
+ desc.pixelformat >> 0 & 0xff,
367
+ desc.pixelformat >> 8 & 0xff,
368
+ desc.pixelformat >> 16 & 0xff,
369
+ desc.pixelformat >> 24 & 0xff);
370
+ rb_ivar_set(fmt, id_iv_fcc, fcc);
371
+ rb_ivar_set(fmt, id_iv_desc, rb_str_new2(desc.description));
372
+
373
+ rb_ary_push(ret, fmt);
374
+ }
375
+
376
+ return ret;
377
+ }
378
+
379
+ static void
380
+ make_dummy_capabilities(camera_t* ptr, VALUE ary, int max_width, int max_height)
381
+ {
382
+ struct v4l2_frmsize_discrete dsize;
383
+ VALUE capa;
384
+
385
+ if (max_width > max_height) {
386
+ /*
387
+ * when landscape
388
+ */
389
+
390
+ for (dsize.width = 160; dsize.width < max_width; dsize.width *= 2) {
391
+ dsize.height = (dsize.width * 9) / 16;
392
+
393
+ capa = rb_obj_alloc(frame_cap_klass);
394
+ rb_ivar_set(capa, id_iv_width, INT2NUM(dsize.width));
395
+ rb_ivar_set(capa, id_iv_height, INT2NUM(dsize.height));
396
+ rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &dsize));
397
+
398
+ rb_ary_push(ary, capa);
399
+
400
+ dsize.height = (dsize.width * 3) / 4;
401
+
402
+ capa = rb_obj_alloc(frame_cap_klass);
403
+ rb_ivar_set(capa, id_iv_width, INT2NUM(dsize.width));
404
+ rb_ivar_set(capa, id_iv_height, INT2NUM(dsize.height));
405
+ rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &dsize));
406
+
407
+ rb_ary_push(ary, capa);
408
+ }
409
+
410
+ } else {
411
+ /*
412
+ * when portrate
413
+ */
414
+
415
+ dsize.height = 160;
416
+
417
+ for (dsize.height = 160; dsize.height < max_height; dsize.height *= 2) {
418
+ dsize.width = (dsize.height * 9) / 16;
419
+
420
+ capa = rb_obj_alloc(frame_cap_klass);
421
+ rb_ivar_set(capa, id_iv_width, INT2NUM(dsize.width));
422
+ rb_ivar_set(capa, id_iv_height, INT2NUM(dsize.height));
423
+ rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &dsize));
424
+
425
+ rb_ary_push(ary, capa);
426
+
427
+ dsize.width = (dsize.height * 3) / 4;
428
+
429
+ capa = rb_obj_alloc(frame_cap_klass);
430
+ rb_ivar_set(capa, id_iv_width, INT2NUM(dsize.width));
431
+ rb_ivar_set(capa, id_iv_height, INT2NUM(dsize.height));
432
+ rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &dsize));
433
+
434
+ rb_ary_push(ary, capa);
435
+ }
436
+ }
437
+ }
438
+
439
+ static VALUE
440
+ rb_camera_get_frame_capabilities(VALUE self, VALUE fmt)
441
+ {
442
+ VALUE ret;
443
+ camera_t* ptr;
444
+ int i;
445
+ int j;
446
+
447
+ int err;
448
+ struct v4l2_frmsizeenum size;
449
+
450
+ VALUE capa;
451
+ VALUE list;
452
+ VALUE rate;
453
+
454
+ Check_Type(fmt, T_SYMBOL);
455
+
456
+ Data_Get_Struct(self, camera_t, ptr);
457
+
458
+ ret = rb_ary_new();
459
+
460
+ for (i = 0; ;i++){
461
+ err = camera_get_frame_size(ptr, to_pixfmt(fmt), i, &size);
462
+ if (err) break;
463
+
464
+ if (size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
465
+ capa = rb_obj_alloc(frame_cap_klass);
466
+ rb_ivar_set(capa, id_iv_width, INT2NUM(size.discrete.width));
467
+ rb_ivar_set(capa, id_iv_height, INT2NUM(size.discrete.height));
468
+ rb_ivar_set(capa, id_iv_rate, get_framerate_list(ptr, &size.discrete));
469
+
470
+ rb_ary_push(ret, capa);
471
+
472
+ } else if (size.type == V4L2_FRMSIZE_TYPE_STEPWISE) {
473
+ make_dummy_capabilities(ptr, ret,
474
+ size.stepwise.max_width,
475
+ size.stepwise.max_height);
476
+ break;
477
+ }
478
+ }
479
+
480
+ return ret;
481
+ }
482
+
483
+ static VALUE
484
+ rb_camera_set_control(VALUE self, VALUE id, VALUE val)
485
+ {
486
+ camera_t* ptr;
487
+ int err;
488
+
489
+ Data_Get_Struct(self, camera_t, ptr);
490
+
491
+ err = camera_set_control(ptr, FIX2INT(id), FIX2INT(val));
492
+ if (err) {
493
+ rb_raise(rb_eRuntimeError, "set control failed.");
494
+ }
495
+
496
+ return Qnil;
497
+ }
498
+
499
+ static VALUE
500
+ rb_camera_get_control(VALUE self, VALUE id)
501
+ {
502
+ camera_t* ptr;
503
+ int err;
504
+ int32_t value;
505
+
506
+ Data_Get_Struct( self, camera_t, ptr);
507
+
508
+ err = camera_get_control(ptr, FIX2INT(id), &value);
509
+ if (err) {
510
+ rb_raise(rb_eRuntimeError, "get control failed.");
511
+ }
512
+
513
+ return INT2FIX(value);
514
+ }
515
+
516
+ static VALUE
517
+ rb_camera_set_format(VALUE self, VALUE fmt)
518
+ {
519
+ camera_t* ptr;
520
+ int err;
521
+
522
+ /*
523
+ * argument check
524
+ */
525
+ Check_Type(fmt, T_SYMBOL);
526
+
527
+ /*
528
+ * strip object
529
+ */
530
+ Data_Get_Struct(self, camera_t, ptr);
531
+
532
+ /*
533
+ * set parameter
534
+ */
535
+ err = camera_set_format(ptr, to_pixfmt(fmt));
536
+ if (err) {
537
+ rb_raise(rb_eRuntimeError, "set format failed.");
538
+ }
539
+
540
+ return Qnil;
541
+ }
542
+
543
+ static VALUE
544
+ rb_camera_get_image_width(VALUE self)
545
+ {
546
+ int ret;
547
+ camera_t* ptr;
548
+ int err;
549
+
550
+ /*
551
+ * strip object
552
+ */
553
+ Data_Get_Struct(self, camera_t, ptr);
554
+
555
+ /*
556
+ * get parameter
557
+ */
558
+ err = camera_get_image_width(ptr, &ret);
559
+ if (err) {
560
+ rb_raise(rb_eRuntimeError, "get image width failed.");
561
+ }
562
+
563
+ return INT2FIX(ret);
564
+ }
565
+
566
+ static VALUE
567
+ rb_camera_set_image_width(VALUE self, VALUE val)
568
+ {
569
+ camera_t* ptr;
570
+ int err;
571
+
572
+ /*
573
+ * argument check
574
+ */
575
+ Check_Type(val, T_FIXNUM);
576
+
577
+ /*
578
+ * strip object
579
+ */
580
+ Data_Get_Struct(self, camera_t, ptr);
581
+
582
+ /*
583
+ * set parameter
584
+ */
585
+ err = camera_set_image_width(ptr, FIX2INT(val));
586
+ if (err) {
587
+ rb_raise(rb_eRuntimeError, "set image width failed.");
588
+ }
589
+
590
+ return Qnil;
591
+ }
592
+
593
+ static VALUE
594
+ rb_camera_get_image_height(VALUE self)
595
+ {
596
+ int ret;
597
+ camera_t* ptr;
598
+ int err;
599
+
600
+ /*
601
+ * strip object
602
+ */
603
+ Data_Get_Struct(self, camera_t, ptr);
604
+
605
+ /*
606
+ * get parameter
607
+ */
608
+ err = camera_get_image_height(ptr, &ret);
609
+ if (err) {
610
+ rb_raise(rb_eRuntimeError, "get image height failed.");
611
+ }
612
+
613
+ return INT2FIX(ret);
614
+ }
615
+
616
+ static VALUE
617
+ rb_camera_set_image_height(VALUE self, VALUE val)
618
+ {
619
+ camera_t* ptr;
620
+ int err;
621
+
622
+ /*
623
+ * argument check
624
+ */
625
+ Check_Type(val, T_FIXNUM);
626
+
627
+ /*
628
+ * strip object
629
+ */
630
+ Data_Get_Struct(self, camera_t, ptr);
631
+
632
+ /*
633
+ * set parameter
634
+ */
635
+ err = camera_set_image_height(ptr, FIX2INT(val));
636
+ if (err) {
637
+ rb_raise(rb_eRuntimeError, "set image height failed.");
638
+ }
639
+
640
+ return Qnil;
641
+ }
642
+
643
+ static VALUE
644
+ rb_camera_get_framerate(VALUE self)
645
+ {
646
+ return Qnil;
647
+ }
648
+
649
+ static VALUE
650
+ rb_camera_set_framerate(VALUE self, VALUE val)
651
+ {
652
+ camera_t* ptr;
653
+ int num;
654
+ int denom;
655
+ int err;
656
+
657
+ /*
658
+ * argument check
659
+ */
660
+ switch (TYPE(val)) {
661
+ case T_FIXNUM:
662
+ num = 1;
663
+ denom = FIX2INT(val);
664
+ break;
665
+
666
+ case T_FLOAT:
667
+ num = 1000;
668
+ denom = (int)(NUM2DBL(val) * 1000.0);
669
+ break;
670
+
671
+ case T_RATIONAL:
672
+ num = FIX2INT(rb_rational_den(val));
673
+ denom = FIX2INT(rb_rational_num(val));
674
+ break;
675
+
676
+ default:
677
+ rb_raise(rb_eArgError, "illeagal framerate value.");
678
+ }
679
+
680
+ /*
681
+ * strip object
682
+ */
683
+ Data_Get_Struct(self, camera_t, ptr);
684
+
685
+ /*
686
+ * set framerate
687
+ */
688
+ err = camera_set_framerate(ptr, num, denom);
689
+ if (err) {
690
+ rb_raise(rb_eRuntimeError, "set framerate failed.");
691
+ }
692
+
693
+ return Qnil;
694
+ }
695
+
696
+ static VALUE
697
+ rb_camera_state( VALUE self)
698
+ {
699
+ camera_t* ptr;
700
+ const char* str;
701
+
702
+ /*
703
+ * strip object
704
+ */
705
+ Data_Get_Struct(self, camera_t, ptr);
706
+
707
+ /*
708
+ * convert state code
709
+ */
710
+ switch (ptr->state) {
711
+ case -1:
712
+ str = "ERROR";
713
+ break;
714
+
715
+ case 0:
716
+ str = "FINALIZED";
717
+ break;
718
+
719
+ case 1:
720
+ str = "INITIALIZED";
721
+ break;
722
+
723
+ case 2:
724
+ str = "PREAPARE";
725
+ break;
726
+
727
+ case 3:
728
+ str = "READY";
729
+ break;
730
+
731
+ case 4:
732
+ str = "ST_REQUESTED";
733
+ break;
734
+
735
+ default:
736
+ str = "unknown";
737
+ break;
738
+ }
739
+
740
+ return ID2SYM(rb_intern(str));
741
+ }
742
+
743
+ static VALUE
744
+ rb_camera_start(VALUE self)
745
+ {
746
+ int err;
747
+ camera_t* ptr;
748
+
749
+ /*
750
+ * strip object
751
+ */
752
+ Data_Get_Struct(self, camera_t, ptr);
753
+
754
+ /*
755
+ * convert
756
+ */
757
+ err = camera_start(ptr);
758
+ if (err) {
759
+ rb_raise(rb_eRuntimeError, "start capture failed.");
760
+ }
761
+
762
+ return Qnil;
763
+ }
764
+
765
+ static VALUE
766
+ rb_camera_stop(VALUE self)
767
+ {
768
+ int err;
769
+ camera_t* ptr;
770
+
771
+ /*
772
+ * strip object
773
+ */
774
+ Data_Get_Struct(self, camera_t, ptr);
775
+
776
+ /*
777
+ * convert
778
+ */
779
+ err = camera_stop(ptr);
780
+ if (err) {
781
+ rb_raise(rb_eRuntimeError, "stop capture failed.");
782
+ }
783
+
784
+ return Qnil;
785
+ }
786
+
787
+
788
+ static VALUE
789
+ rb_camera_capture(VALUE self)
790
+ {
791
+ VALUE ret;
792
+ camera_t* ptr;
793
+ size_t used;
794
+ int err;
795
+
796
+ /*
797
+ * strip object
798
+ */
799
+ Data_Get_Struct(self, camera_t, ptr);
800
+
801
+ /*
802
+ * allocate return value.
803
+ */
804
+ ret = rb_str_buf_new(ptr->image_size);
805
+ rb_str_set_len(ret, ptr->image_size);
806
+
807
+ /*
808
+ * do capture
809
+ */
810
+ err = camera_get_image(ptr, RSTRING_PTR(ret), &used);
811
+ if (err) {
812
+ rb_raise(rb_eRuntimeError, "capture failed.");
813
+ }
814
+
815
+ if (ptr->image_size != used) {
816
+ rb_str_set_len(ret, used);
817
+ }
818
+
819
+ return ret;
820
+ }
821
+
822
+ static VALUE
823
+ rb_camera_is_busy(VALUE self)
824
+ {
825
+ camera_t* ptr;
826
+ int err;
827
+ int busy;
828
+
829
+ /*
830
+ * strip object
831
+ */
832
+ Data_Get_Struct(self, camera_t, ptr);
833
+
834
+ /*
835
+ * do check
836
+ */
837
+ err = camera_check_busy(ptr, &busy);
838
+ if (err) {
839
+ rb_raise(rb_eRuntimeError, "check failed.");
840
+ }
841
+
842
+ return (busy)? Qtrue: Qfalse;
843
+ }
844
+
845
+ static VALUE
846
+ rb_camera_is_error(VALUE self)
847
+ {
848
+ camera_t* ptr;
849
+ int err;
850
+ int error;
851
+
852
+ /*
853
+ * strip object
854
+ */
855
+ Data_Get_Struct(self, camera_t, ptr);
856
+
857
+ /*
858
+ * do check
859
+ */
860
+ err = camera_check_error(ptr, &error);
861
+ if (err) {
862
+ rb_raise(rb_eRuntimeError, "check failed.");
863
+ }
864
+
865
+ return (error)? Qtrue: Qfalse;
866
+ }
867
+
868
+ void
869
+ Init_v4l2()
870
+ {
871
+ rb_require("monitor");
872
+
873
+ module = rb_define_module("Video4Linux2");
874
+ camera_klass = rb_define_class_under(module, "Camera", rb_cObject);
875
+
876
+ rb_define_alloc_func(camera_klass, rb_camera_alloc);
877
+ rb_define_method(camera_klass, "initialize", rb_camera_initialize, 1);
878
+ rb_define_method(camera_klass, "close", rb_camera_close, 0);
879
+ rb_define_method(camera_klass, "controls", rb_camera_get_controls, 0);
880
+ rb_define_method(camera_klass,
881
+ "support_formats", rb_camera_get_support_formats, 0);
882
+ rb_define_method(camera_klass,
883
+ "frame_capabilities", rb_camera_get_frame_capabilities, 1);
884
+ rb_define_method(camera_klass, "set_control", rb_camera_set_control, 2);
885
+ rb_define_method(camera_klass, "get_control", rb_camera_get_control, 1);
886
+ rb_define_method(camera_klass, "format=", rb_camera_set_format, 1);
887
+ rb_define_method(camera_klass, "image_width", rb_camera_get_image_width, 0);
888
+ rb_define_method(camera_klass, "image_width=", rb_camera_set_image_width, 1);
889
+ rb_define_method(camera_klass, "image_height", rb_camera_get_image_height,0);
890
+ rb_define_method(camera_klass, "image_height=", rb_camera_set_image_height,1);
891
+ rb_define_method(camera_klass, "framerate", rb_camera_get_framerate, 0);
892
+ rb_define_method(camera_klass, "framerate=", rb_camera_set_framerate, 1);
893
+ rb_define_method(camera_klass, "state", rb_camera_state, 0);
894
+ rb_define_method(camera_klass, "start", rb_camera_start, 0);
895
+ rb_define_method(camera_klass, "stop", rb_camera_stop, 0);
896
+ rb_define_method(camera_klass, "capture", rb_camera_capture, 0);
897
+ rb_define_method(camera_klass, "busy?", rb_camera_is_busy, 0);
898
+ rb_define_method(camera_klass, "error?", rb_camera_is_error, 0);
899
+
900
+ rb_define_attr(camera_klass, "name", !0, 0);
901
+ rb_define_attr(camera_klass, "driver", !0, 0);
902
+ rb_define_attr(camera_klass, "bus", !0, 0);
903
+
904
+ rb_define_singleton_method( camera_klass, "open", rb_camera_open, 1);
905
+
906
+ control_klass = rb_define_class_under(camera_klass,
907
+ "Control", rb_cObject);
908
+ rb_define_attr(control_klass, "name", !0, 0);
909
+ rb_define_attr(control_klass, "id", !0, 0);
910
+ rb_define_attr(control_klass, "value", !0, 0);
911
+
912
+ integer_klass = rb_define_class_under(camera_klass,
913
+ "IntegerControl", control_klass);
914
+ rb_define_attr(integer_klass, "min", !0, 0);
915
+ rb_define_attr(integer_klass, "max", !0, 0);
916
+ rb_define_attr(integer_klass, "step", !0, 0);
917
+ rb_define_attr(integer_klass, "default", !0, 0);
918
+
919
+ boolean_klass = rb_define_class_under(camera_klass,
920
+ "BooleanControl", control_klass);
921
+ rb_define_attr(boolean_klass, "default", !0, 0);
922
+
923
+ menu_klass = rb_define_class_under(camera_klass,
924
+ "MenuControl", control_klass);
925
+ rb_define_attr(menu_klass, "default", !0, 0);
926
+ rb_define_attr(menu_klass, "items", !0, 0);
927
+
928
+ menu_item_klass = rb_define_class_under(camera_klass,
929
+ "MenuItem", rb_cObject);
930
+ rb_define_attr(menu_item_klass, "name", !0, 0);
931
+ rb_define_attr(menu_item_klass, "index", !0, 0);
932
+
933
+ frame_cap_klass = rb_define_class_under(camera_klass,
934
+ "FrameCapability", rb_cObject);
935
+ rb_define_attr(frame_cap_klass, "width", !0, 0);
936
+ rb_define_attr(frame_cap_klass, "height", !0, 0);
937
+ rb_define_attr(frame_cap_klass, "rate", !0, 0);
938
+
939
+ fmt_desc_klass = rb_define_class_under(camera_klass,
940
+ "FormatDescription", rb_cObject);
941
+ rb_define_attr(fmt_desc_klass, "fcc", !0, 0);
942
+ rb_define_attr(fmt_desc_klass, "description", !0, 0);
943
+
944
+ id_yuyv = rb_intern_const("YUYV");
945
+ id_yuv422 = rb_intern_const("YUV422");
946
+ id_nv12 = rb_intern_const("NV12");
947
+ id_nv21 = rb_intern_const("NV21");
948
+ id_nv16 = rb_intern_const("NV16");
949
+ id_rgb565 = rb_intern_const("RGB565");
950
+ id_mjpeg = rb_intern_const("MJPEG");
951
+ id_h264 = rb_intern_const("H264");
952
+ id_iv_name = rb_intern_const("@name");
953
+ id_iv_driver = rb_intern_const("@driver");
954
+ id_iv_bus = rb_intern_const("@bus");
955
+ id_iv_id = rb_intern_const("@id");
956
+ id_iv_min = rb_intern_const("@max");
957
+ id_iv_max = rb_intern_const("@min");
958
+ id_iv_step = rb_intern_const("@step");
959
+ id_iv_default = rb_intern_const("@default");
960
+ id_iv_items = rb_intern_const("@items");
961
+ id_iv_index = rb_intern_const("@index");
962
+ id_iv_width = rb_intern_const("@width");
963
+ id_iv_height = rb_intern_const("@height");
964
+ id_iv_rate = rb_intern_const("@rate");
965
+ id_iv_fcc = rb_intern_const("@fcc");
966
+ id_iv_desc = rb_intern_const("@description");
967
+ }