gphoto4ruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,49 @@
1
+ GPhoto2::Camera
2
+ Класс для управления камерами, подключенными через usb-порты к компьютеру.
3
+ Следует написать require "gphoto4ruby"
4
+
5
+ GPhoto2::Camera.ports() -> Array
6
+ Метод класса. Возвращает массив, содержащий пути (path) usb-портов, к которым подключены камеры, если камер более одной.
7
+
8
+ GPhoto2::Camera.new() -> GPhoto2::Camera
9
+ Конструктор класса. Создает объект для управления первой авто-определенной камерой (обычно это камера, которая была подключена последней).
10
+
11
+ GPhoto2::Camera.new(port) -> GPhoto2::Camera
12
+ Конструктор класса. Создает объект для управления камерой, подключенной к заданному порту. Актуально при подключении более одной камеры.
13
+ port (String) -- путь (path) порта с камерой. Следует использовать элементы массива, возвращаемого методом класса GPhoto2::Camera.ports
14
+ Пример:
15
+ cams = Array.new
16
+ GPhoto2::Camera.ports.each do |port|
17
+ cams.push(GPhoto2::Camera.new(port))
18
+ end
19
+
20
+ configs() -> Array
21
+ Метод объекта. Возвращает массив с именами (name) доступных для изменения настроек камеры.
22
+
23
+ [config_name] -> String или Float
24
+ Метод объекта. Возвращает значение настройки с именем config_name.
25
+ config_name (String или Symbol) -- имя (name) настройки камеры. Следует использовать элементы массива, возвращаемые методом configs().
26
+ Пример:
27
+ cam[:focallength] -> 10.5
28
+ cam["f-number"] -> "f/4"
29
+ cam[cam.configs[0]]
30
+
31
+ [config_name, directive] -> Array
32
+ Метод объекта. Возвращает информацию о настройке в зависимости от директивы directive.
33
+ config_name (String или Symbol) -- имя (name) настройки камеры. Следует использовать элементы массива, возвращаемые методом configs().
34
+ directive (Symbol) -- указывает на информацию, которую следует выдать
35
+ :all -- возвращается массив с допустимыми значениями настройки.
36
+ Пример:
37
+ cam["exptime", :all] -> ["0.002", "0.003", ...]
38
+
39
+ [config_name] = value -> String или Float
40
+ Метод объекта. Изменяет значение указанной настройки на новое.
41
+ config_name (String или Symbol) -- имя (name) настройки камеры. Следует использовать элементы массива, возвращаемые методом configs().
42
+ value (String или Float) -- новое значение настройки. Следует использовать элементы массива, возвращаемые методом [] с директивой :all.
43
+ Пример:
44
+ cam[:exptime] = "0.010" -> "0.010"
45
+ cam["f-number"] = cam["f-number", :all][3]
46
+
47
+ capture() -> GPhoto2::Camera
48
+ Метод объекта. Посылает сигнал на камеру для съемки изображения.
49
+
data/ext/extconf.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "mkmf"
2
+
3
+ dir_config("gphoto4ruby", "/usr/local")
4
+ if have_library("gphoto2")
5
+ create_makefile("gphoto4ruby")
6
+ else
7
+ raise "You need gphoto2 installed to compile and use this library"
8
+ end
data/ext/gphoto4ruby.c ADDED
@@ -0,0 +1,459 @@
1
+ /**
2
+ *
3
+ * Copyright 2008 neq4 company <http://neq4.com>
4
+ * Author: Sergey Kruk <sergey.kruk@gmail.com>
5
+ *
6
+ * This file is part of GPhoto4Ruby.
7
+ *
8
+ * GPhoto4Ruby is free software: you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation, either
11
+ * version 3 of the License, or (at your option) any later version.
12
+ *
13
+ * GPhoto4Ruby is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with GPhoto4Ruby. If not, see <http://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+ #include <stdlib.h>
24
+ #include <stdio.h>
25
+ #include <string.h>
26
+ #include <gphoto2/gphoto2.h>
27
+ #include <ruby.h>
28
+ #include "gphoto4ruby.h"
29
+
30
+
31
+ static VALUE rb_mGPhoto2;
32
+ static VALUE rb_cGPhoto2Camera;
33
+ static VALUE rb_cGPhoto2Exception;
34
+ static VALUE rb_cGPhoto2ConfigurationError;
35
+ static VALUE rb_cGPhoto2ProgrammerError;
36
+
37
+ static void rb_raise_gp_result(int retval) {
38
+ rb_raise(rb_cGPhoto2Exception, "LibGPhoto2 function returned: %s", gp_result_as_string(retval));
39
+ }
40
+
41
+ static void rb_raise_programmer_error(const char* fName) {
42
+ rb_raise(rb_cGPhoto2ProgrammerError, "Program was not supposed to get here. Function: %s", fName);
43
+ }
44
+
45
+ static VALUE getRadio(CameraWidget *cc) {
46
+ int retval;
47
+ const char *val;
48
+ retval = gp_widget_get_value(cc, &val);
49
+ if (retval == GP_OK) {
50
+ return rb_str_new2(val);
51
+ } else {
52
+ rb_raise_gp_result(retval);
53
+ return Qnil;
54
+ }
55
+ }
56
+
57
+ static VALUE listRadio(CameraWidget *cc) {
58
+ int retval, i, choicesTotal;
59
+ const char *choice;
60
+ VALUE arr;
61
+
62
+ choicesTotal = gp_widget_count_choices(cc);
63
+ arr = rb_ary_new();
64
+ for (i = 0; i < choicesTotal; i++) {
65
+ retval = gp_widget_get_choice(cc, i, &choice);
66
+ if (retval == GP_OK) {
67
+ rb_ary_push(arr, rb_str_new2(choice));
68
+ } else {
69
+ rb_raise_gp_result(retval);
70
+ return Qnil;
71
+ }
72
+ }
73
+ return arr;
74
+
75
+ static VALUE setRadio(GPhoto2Camera *c, VALUE newVal) {
76
+ int retval, i, choicesTotal;
77
+ const char *choice;
78
+ const char *val;
79
+
80
+ Check_Type(newVal, T_STRING);
81
+ val = RSTRING(newVal)->ptr;
82
+
83
+ choicesTotal = gp_widget_count_choices(c->childConfig);
84
+ for (i = 0; i < choicesTotal; i++) {
85
+ gp_widget_get_choice(c->childConfig, i, &choice);
86
+ if (strcmp(choice, val) == 0) {
87
+ retval = gp_widget_set_value(c->childConfig, val);
88
+ if (retval == GP_OK) {
89
+ retval = gp_camera_set_config(c->camera, c->config, c->context);
90
+ if (retval == GP_OK) {
91
+ return newVal;
92
+ }
93
+ }
94
+ }
95
+ }
96
+ if (retval != GP_OK) {
97
+ rb_raise_gp_result(retval);
98
+ } else {
99
+ rb_raise(rb_cGPhoto2ConfigurationError, "Value '%s' is not allowed", val);
100
+ }
101
+ return Qnil;
102
+ }
103
+
104
+ static VALUE getRange(CameraWidget *cc) {
105
+ int retval;
106
+ float val;
107
+ retval = gp_widget_get_value(cc, &val);
108
+ if (retval == GP_OK) {
109
+ return rb_float_new(val);
110
+ } else {
111
+ rb_raise_gp_result(retval);
112
+ return Qnil;
113
+ }
114
+ }
115
+
116
+ static VALUE listRange(CameraWidget *cc) {
117
+ int retval;
118
+ float min, max, inc, i;
119
+ VALUE arr;
120
+
121
+ retval = gp_widget_get_range(cc, &min, &max, &inc);
122
+ if ((retval == GP_OK) && (inc > 0)) {
123
+ arr = rb_ary_new();
124
+ for (i = min; i <= max; i = i + inc) {
125
+ rb_ary_push(arr, rb_float_new(i));
126
+ }
127
+ return arr;
128
+ } else if (retval != GP_OK) {
129
+ rb_raise_gp_result(retval);
130
+ } else {
131
+ return rb_ary_new();
132
+ }
133
+ return Qnil;
134
+ }
135
+
136
+ static VALUE setRange(GPhoto2Camera *c, VALUE newNum) {
137
+ int retval;
138
+ float min, max, inc, i;
139
+ float val;
140
+
141
+ Check_Type(newNum, T_FLOAT);
142
+ val = NUM2DBL(newNum);
143
+
144
+ retval = gp_widget_get_range(c->childConfig, &min, &max, &inc);
145
+ if ((retval == GP_OK) && (val >= min) && (val <= max) && (inc > 0)) {
146
+ for (i = min; i <= max; i = i + inc) {
147
+ if ((val >= i) && (val <= (i+inc))) {
148
+ if ((val - i) > (inc / 2.0)) {
149
+ val = i + inc;
150
+ } else {
151
+ val = i;
152
+ }
153
+ retval = gp_widget_set_value(c->childConfig, &val);
154
+ if (retval == GP_OK) {
155
+ retval = gp_camera_set_config(c->camera, c->config, c->context);
156
+ if (retval == GP_OK) {
157
+ return rb_float_new(val);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ }
163
+ if (retval != GP_OK) {
164
+ rb_raise_gp_result(retval);
165
+ } else {
166
+ rb_raise(rb_cGPhoto2ConfigurationError, "Value has to be in range: %f .. %f", min, max);
167
+ }
168
+ return Qnil;
169
+ }
170
+
171
+ static void populateWithConfigs(CameraWidget *cc, VALUE arr) {
172
+ int retval, i, childrenTotal;
173
+ const char *name;
174
+ CameraWidget *child;
175
+ CameraWidgetType widgettype;
176
+
177
+ retval = gp_widget_get_type(cc, &widgettype);
178
+ if (retval == GP_OK) {
179
+ switch (widgettype) {
180
+ case GP_WIDGET_RADIO:
181
+ case GP_WIDGET_RANGE:
182
+ retval = gp_widget_get_name(cc, &name);
183
+ if (retval == GP_OK) {
184
+ rb_ary_push(arr, rb_str_new2(name));
185
+ }
186
+ break;
187
+ case GP_WIDGET_WINDOW:
188
+ case GP_WIDGET_SECTION:
189
+ childrenTotal = gp_widget_count_children(cc);
190
+ for (i = 0; i < childrenTotal; i ++) {
191
+ retval = gp_widget_get_child(cc, i, &child);
192
+ if (retval == GP_OK) {
193
+ populateWithConfigs(child, arr);
194
+ }
195
+ }
196
+ break;
197
+ }
198
+ }
199
+ if (retval != GP_OK) {
200
+ rb_raise_gp_result(retval);
201
+ }
202
+ }
203
+
204
+ static void camera_mark(GPhoto2Camera *c) {
205
+ }
206
+
207
+ static void camera_free(GPhoto2Camera *c) {
208
+ int retval;
209
+ retval = gp_camera_exit(c->camera, c->context);
210
+ retval = gp_widget_free(c->config);
211
+ retval = gp_camera_free(c->camera);
212
+ free(c->context);
213
+ free(c);
214
+ }
215
+
216
+ static VALUE camera_allocate(VALUE klass) {
217
+ int retval;
218
+ GPhoto2Camera *c;
219
+ c = (GPhoto2Camera*) malloc(sizeof(GPhoto2Camera));
220
+ c->context = gp_context_new();
221
+ retval = gp_camera_new(&(c->camera));
222
+ if (retval == GP_OK) {
223
+ retval = gp_camera_get_config(c->camera, &(c->config), c->context);
224
+ if (retval == GP_OK) {
225
+ return Data_Wrap_Struct(klass, camera_mark, camera_free, c);
226
+ }
227
+ }
228
+ rb_raise_gp_result(retval);
229
+ return Qnil;
230
+ }
231
+
232
+ static VALUE camera_initialize(int argc, VALUE *argv, VALUE self) {
233
+ switch (argc) {
234
+ case 0:
235
+ return self;
236
+ break;
237
+ case 1:
238
+ Check_Type(argv[0], T_STRING);
239
+ int retval, portIndex;
240
+ GPPortInfoList *portInfoList;
241
+ GPPortInfo p;
242
+ GPhoto2Camera *c;
243
+
244
+ Data_Get_Struct(self, GPhoto2Camera, c);
245
+
246
+ retval = gp_port_info_list_new(&portInfoList);
247
+ if (retval == GP_OK) {
248
+ retval = gp_port_info_list_load(portInfoList);
249
+ if (retval == GP_OK) {
250
+ portIndex = gp_port_info_list_lookup_path(portInfoList, RSTRING(argv[0])->ptr);
251
+ if (portIndex >= 0) {
252
+ retval = gp_port_info_list_get_info(portInfoList, portIndex, &p);
253
+ if (retval == GP_OK) {
254
+ retval = gp_camera_set_port_info(c->camera, p);
255
+ if (retval == GP_OK) {
256
+ return self;
257
+ }
258
+ }
259
+ } else {
260
+ rb_raise_gp_result(portIndex);
261
+ return Qnil;
262
+ }
263
+ }
264
+ }
265
+ rb_raise_gp_result(retval);
266
+ return Qnil;
267
+ default:
268
+ rb_raise(rb_eArgError, "Wrong number of arguments (%d for 0 or 1)", argc);
269
+ return Qnil;
270
+ }
271
+ }
272
+
273
+ static VALUE camera_class_ports(VALUE klass) {
274
+ int retval, i, portsTotal;
275
+ GPPortInfoList *portInfoList;
276
+ GPPortInfo p;
277
+ VALUE arr;
278
+
279
+ retval = gp_port_info_list_new(&portInfoList);
280
+ if (retval == GP_OK) {
281
+ retval = gp_port_info_list_load(portInfoList);
282
+ if (retval == GP_OK) {
283
+ portsTotal = gp_port_info_list_count(portInfoList);
284
+ arr = rb_ary_new();
285
+ for(i = 0; i < portsTotal; i++) {
286
+ retval = gp_port_info_list_get_info(portInfoList, i, &p);
287
+ if ((retval == GP_OK) && (strlen(p.path) > 4) && (strncmp(p.path, "usb:", 4) == 0)) {
288
+ rb_ary_push(arr, rb_str_new2(p.path));
289
+ }
290
+ }
291
+ retval = gp_port_info_list_free(portInfoList);
292
+ if (retval == GP_OK) {
293
+ return arr;
294
+ }
295
+ }
296
+ }
297
+ rb_raise_gp_result(retval);
298
+ return Qnil;
299
+ }
300
+
301
+ static VALUE camera_capture(VALUE self) {
302
+ int retval;
303
+ GPhoto2Camera *c;
304
+
305
+ Data_Get_Struct(self, GPhoto2Camera, c);
306
+
307
+ retval = gp_camera_capture(c->camera, GP_CAPTURE_IMAGE, &(c->filepath), c->context);
308
+ if (retval == GP_OK) {
309
+ // printf("captured: %s/%s\n", c->filepath.folder, c->filepath.name);
310
+ return self;
311
+ } else {
312
+ rb_raise_gp_result(retval);
313
+ return Qnil;
314
+ }
315
+ }
316
+
317
+ static VALUE camera_get_configs(VALUE self) {
318
+ GPhoto2Camera *c;
319
+ VALUE arr = rb_ary_new();
320
+
321
+ Data_Get_Struct(self, GPhoto2Camera, c);
322
+
323
+ populateWithConfigs(c->config, arr);
324
+
325
+ return arr;
326
+ }
327
+
328
+ static VALUE camera_get_value(int argc, VALUE *argv, VALUE self) {
329
+ int retval;
330
+ const char *name;
331
+ GPhoto2Camera *c;
332
+ CameraWidgetType widgettype;
333
+ VALUE str, dir;
334
+
335
+ switch (argc) {
336
+ case 1:
337
+ str = argv[0];
338
+ break;
339
+ case 2:
340
+ str = argv[0];
341
+ dir = argv[1];
342
+ break;
343
+ default:
344
+ rb_raise(rb_eArgError, "Wrong number of arguments (%d for 1 or 2)", argc);
345
+ return Qnil;
346
+ }
347
+
348
+ switch (TYPE(str)) {
349
+ case T_STRING:
350
+ name = RSTRING(str)->ptr;
351
+ break;
352
+ case T_SYMBOL:
353
+ name = rb_id2name(rb_to_id(str));
354
+ break;
355
+ default:
356
+ rb_raise(rb_eTypeError, "Not valid parameter type");
357
+ return Qnil;
358
+ }
359
+
360
+ Data_Get_Struct(self, GPhoto2Camera, c);
361
+
362
+ retval = gp_widget_get_child_by_name(c->config, name, &(c->childConfig));
363
+ if (retval == GP_OK) {
364
+ retval = gp_widget_get_type(c->childConfig, &widgettype);
365
+ if (retval == GP_OK) {
366
+ switch (widgettype) {
367
+ case GP_WIDGET_RADIO:
368
+ if (argc == 1) {
369
+ return getRadio(c->childConfig);
370
+ } else if (strcmp(rb_id2name(rb_to_id(dir)), "all") == 0) {
371
+ return listRadio(c->childConfig);
372
+ } else {
373
+ rb_raise(rb_cGPhoto2ConfigurationError, "Second parameter not valid");
374
+ return Qnil;
375
+ }
376
+ break;
377
+ case GP_WIDGET_RANGE:
378
+ if (argc == 1) {
379
+ return getRange(c->childConfig);
380
+ } else if (strcmp(rb_id2name(rb_to_id(dir)), "all") == 0) {
381
+ return listRange(c->childConfig);
382
+ } else {
383
+ rb_raise(rb_cGPhoto2ConfigurationError, "Second parameter not valid");
384
+ return Qnil;
385
+ }
386
+ break;
387
+ default:
388
+ rb_raise(rb_cGPhoto2ConfigurationError, "Not supported yet");
389
+ return Qnil;
390
+ }
391
+ }
392
+ }
393
+ if (retval != GP_OK) {
394
+ rb_raise_gp_result(retval);
395
+ } else {
396
+ rb_raise_programmer_error("camera_get_value");
397
+ }
398
+ return Qnil;
399
+ }
400
+
401
+ static VALUE camera_set_value(VALUE self, VALUE str, VALUE newVal) {
402
+ int retval;
403
+ const char *name;
404
+ GPhoto2Camera *c;
405
+ CameraWidgetType widgettype;
406
+
407
+ switch (TYPE(str)) {
408
+ case T_STRING:
409
+ name = RSTRING(str)->ptr;
410
+ break;
411
+ case T_SYMBOL:
412
+ name = rb_id2name(rb_to_id(str));
413
+ break;
414
+ default:
415
+ rb_raise(rb_eTypeError, "Not valid parameter type");
416
+ return Qnil;
417
+ }
418
+
419
+ Data_Get_Struct(self, GPhoto2Camera, c);
420
+
421
+ retval = gp_widget_get_child_by_name(c->config, name, &(c->childConfig));
422
+ if (retval == GP_OK) {
423
+ retval = gp_widget_get_type(c->childConfig, &widgettype);
424
+ if (retval == GP_OK) {
425
+ switch (widgettype) {
426
+ case GP_WIDGET_RADIO:
427
+ return setRadio(c, newVal);
428
+ break;
429
+ case GP_WIDGET_RANGE:
430
+ return setRange(c, newVal);
431
+ break;
432
+ default:
433
+ rb_raise(rb_cGPhoto2ConfigurationError, "Cannot access this setting");
434
+ return Qnil;
435
+ }
436
+ }
437
+ }
438
+ if (retval != GP_OK) {
439
+ rb_raise_gp_result(retval);
440
+ } else {
441
+ rb_raise_programmer_error("camera_set_value");
442
+ }
443
+ return Qnil;
444
+ }
445
+
446
+ void Init_gphoto4ruby() {
447
+ rb_mGPhoto2 = rb_define_module("GPhoto2");
448
+ rb_cGPhoto2Camera = rb_define_class_under(rb_mGPhoto2, "Camera", rb_cObject);
449
+ rb_cGPhoto2Exception = rb_define_class_under(rb_mGPhoto2, "Exception", rb_eStandardError);
450
+ rb_cGPhoto2ConfigurationError = rb_define_class_under(rb_mGPhoto2, "ConfigurationError", rb_eStandardError);
451
+ rb_cGPhoto2ProgrammerError = rb_define_class_under(rb_mGPhoto2, "ProgrammerError", rb_eStandardError);
452
+ rb_define_alloc_func(rb_cGPhoto2Camera, camera_allocate);
453
+ rb_define_module_function(rb_cGPhoto2Camera, "ports", camera_class_ports, 0);
454
+ rb_define_method(rb_cGPhoto2Camera, "initialize", camera_initialize, -1);
455
+ rb_define_method(rb_cGPhoto2Camera, "configs", camera_get_configs, 0);
456
+ rb_define_method(rb_cGPhoto2Camera, "[]", camera_get_value, -1);
457
+ rb_define_method(rb_cGPhoto2Camera, "[]=", camera_set_value, 2);
458
+ rb_define_method(rb_cGPhoto2Camera, "capture", camera_capture, 0);
459
+ }