v4l2-ruby 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }