gphoto4ruby 0.1.6 → 0.2.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/gphoto4ruby.c CHANGED
@@ -26,1037 +26,9 @@
26
26
  #include <string.h>
27
27
  #include <gphoto2/gphoto2.h>
28
28
  #include <ruby.h>
29
- #include "gphoto4ruby.h"
30
-
31
- static void rb_raise_gp_result(int retval) {
32
- rb_raise(rb_cGPhoto2Exception, "LibGPhoto2 function returned: %s", gp_result_as_string(retval));
33
- }
34
-
35
- static int gp_result_check(int retval) {
36
- if (retval < GP_OK) {
37
- rb_raise_gp_result(retval);
38
- }
39
- return retval;
40
- }
41
-
42
- static VALUE getRadio(CameraWidget *cc) {
43
- const char *val;
44
- gp_result_check(gp_widget_get_value(cc, &val));
45
- return rb_str_new2(val);
46
- }
47
-
48
- static VALUE listRadio(CameraWidget *cc) {
49
- int i, choicesTotal;
50
- const char *choice;
51
- VALUE arr;
52
-
53
- choicesTotal = gp_result_check(gp_widget_count_choices(cc));
54
- arr = rb_ary_new();
55
- for (i = 0; i < choicesTotal; i++) {
56
- gp_result_check(gp_widget_get_choice(cc, i, &choice));
57
- rb_ary_push(arr, rb_str_new2(choice));
58
- }
59
- return arr;
60
-
61
- static VALUE setRadio(VALUE self, GPhoto2Camera *c, VALUE newVal, int save) {
62
- int i, choicesTotal;
63
- const char *val;
64
-
65
- Check_Type(newVal, T_STRING);
66
- val = RSTRING(newVal)->ptr;
67
-
68
- gp_result_check(gp_widget_set_value(c->childConfig, val));
69
- if (save) {
70
- saveConfigs(self, c);
71
- }
72
- return newVal;
73
- }
74
-
75
- static VALUE getRange(CameraWidget *cc) {
76
- float val;
77
- gp_result_check(gp_widget_get_value(cc, &val));
78
- return rb_float_new(val);
79
- }
80
-
81
- static VALUE listRange(CameraWidget *cc) {
82
- float min, max, inc, i;
83
- VALUE arr;
84
-
85
- gp_result_check(gp_widget_get_range(cc, &min, &max, &inc));
86
- arr = rb_ary_new();
87
- if (inc > 0) {
88
- for (i = min; i <= max; i = i + inc) {
89
- rb_ary_push(arr, rb_float_new(i));
90
- }
91
- } else {
92
- rb_ary_push(arr, rb_float_new(min));
93
- }
94
- return arr;
95
- }
96
-
97
- static VALUE setRange(VALUE self, GPhoto2Camera *c, VALUE newNum, int save) {
98
- float val;
99
-
100
- Check_Type(newNum, T_FLOAT);
101
- val = NUM2DBL(newNum);
102
-
103
- gp_result_check(gp_widget_set_value(c->childConfig, &val));
104
- if (save) {
105
- saveConfigs(self, c);
106
- }
107
- return newNum;
108
- }
109
-
110
- static void saveConfigs(VALUE self, GPhoto2Camera *c) {
111
- VALUE cfgs, cfg_changed, name;
112
- CameraWidgetType widgettype;
113
-
114
- gp_result_check(gp_camera_set_config(c->camera, c->config, c->context));
115
- gp_result_check(gp_camera_get_config(c->camera, &(c->config), c->context));
116
- cfg_changed = rb_iv_get(self, "@configs_changed");
117
- cfgs = rb_iv_get(self, "@configuration");
118
- name = rb_ary_shift(cfg_changed);
119
- while (TYPE(name) != T_NIL) {
120
- gp_result_check(gp_widget_get_child_by_name(c->config, RSTRING(name)->ptr, &(c->childConfig)));
121
- gp_result_check(gp_widget_get_type(c->childConfig, &widgettype));
122
- switch (widgettype) {
123
- case GP_WIDGET_RADIO:
124
- rb_hash_aset(cfgs, name, getRadio(c->childConfig));
125
- break;
126
- case GP_WIDGET_RANGE:
127
- rb_hash_aset(cfgs, name, getRange(c->childConfig));
128
- break;
129
- }
130
- name = rb_ary_shift(cfg_changed);
131
- }
132
- }
133
-
134
- static void populateWithConfigs(CameraWidget *cc, VALUE hash) {
135
- int i, childrenTotal;
136
- const char *name;
137
- CameraWidget *child;
138
- CameraWidgetType widgettype;
139
-
140
- gp_result_check(gp_widget_get_type(cc, &widgettype));
141
- switch (widgettype) {
142
- case GP_WIDGET_RADIO:
143
- gp_result_check(gp_widget_get_name(cc, &name));
144
- rb_hash_aset(hash, rb_str_new2(name), getRadio(cc));
145
- break;
146
- case GP_WIDGET_RANGE:
147
- gp_result_check(gp_widget_get_name(cc, &name));
148
- rb_hash_aset(hash, rb_str_new2(name), getRange(cc));
149
- break;
150
- case GP_WIDGET_WINDOW:
151
- case GP_WIDGET_SECTION:
152
- childrenTotal = gp_result_check(gp_widget_count_children(cc));
153
- for (i = 0; i < childrenTotal; i ++) {
154
- gp_result_check(gp_widget_get_child(cc, i, &child));
155
- populateWithConfigs(child, hash);
156
- }
157
- break;
158
- }
159
- }
160
-
161
- static void camera_mark(GPhoto2Camera *c) {
162
- }
163
-
164
- static void camera_free(GPhoto2Camera *c) {
165
- gp_result_check(gp_camera_exit(c->camera, c->context));
166
- gp_result_check(gp_widget_free(c->config));
167
- gp_result_check(gp_list_free(c->list));
168
- gp_result_check(gp_file_free(c->file));
169
- gp_result_check(gp_camera_free(c->camera));
170
- free(c->virtFolder);
171
- free(c->context);
172
- free(c);
173
- }
174
-
175
- static VALUE camera_allocate(VALUE klass) {
176
- GPhoto2Camera *c;
177
- c = (GPhoto2Camera*) malloc(sizeof(GPhoto2Camera));
178
- c->virtFolder = (char*) malloc(sizeof(char)*100);
179
- strcpy(c->virtFolder, "/");
180
- c->context = gp_context_new();
181
- gp_result_check(gp_camera_new(&(c->camera)));
182
- gp_result_check(gp_list_new(&(c->list)));
183
- gp_result_check(gp_camera_get_config(c->camera, &(c->config), c->context));
184
- gp_result_check(gp_file_new(&(c->file)));
185
- return Data_Wrap_Struct(klass, camera_mark, camera_free, c);
186
- }
187
-
188
- static void camera_event_mark(GPhoto2CameraEvent *ce) {
189
- }
190
-
191
- static void camera_event_free(GPhoto2CameraEvent *ce) {
192
- free(ce);
193
- }
194
-
195
- /*
196
- * call-seq:
197
- * GPhoto2::Camera.new(port=nil)
198
- *
199
- * Returns camera object. Camera should be connected at a time constructor
200
- * is called. If there is more than one camera connected through usb ports,
201
- * port parameter can be passed to specify which camera is addressed with
202
- * object.
203
- *
204
- * Examples:
205
- *
206
- * GPhoto2::Camera.new
207
- * GPhoto2::Capera.new(GPhoto2::Camera.ports[0])
208
- *
209
- */
210
- static VALUE camera_initialize(int argc, VALUE *argv, VALUE self) {
211
- GPhoto2Camera *c;
212
- VALUE cfgs;
213
-
214
- Data_Get_Struct(self, GPhoto2Camera, c);
215
-
216
- switch (argc) {
217
- case 0:
218
- break;
219
- case 1:
220
- Check_Type(argv[0], T_STRING);
221
- int portIndex;
222
- GPPortInfoList *portInfoList;
223
- GPPortInfo p;
224
-
225
- gp_result_check(gp_port_info_list_new(&portInfoList));
226
- gp_result_check(gp_port_info_list_load(portInfoList));
227
- portIndex = gp_result_check(gp_port_info_list_lookup_path(portInfoList, RSTRING(argv[0])->ptr));
228
- gp_result_check(gp_port_info_list_get_info(portInfoList, portIndex, &p));
229
- gp_result_check(gp_camera_set_port_info(c->camera, p));
230
- break;
231
- default:
232
- rb_raise(rb_eArgError, "Wrong number of arguments (%d for 0 or 1)", argc);
233
- return Qnil;
234
- }
235
-
236
- cfgs = rb_hash_new();
237
- populateWithConfigs(c->config, cfgs);
238
- rb_iv_set(self, "@configuration", cfgs);
239
- rb_iv_set(self, "@configs_changed", rb_ary_new());
240
-
241
- return self;
242
- }
243
-
244
- /*
245
- * call-seq:
246
- * GPhoto2::Camera.ports => array
247
- *
248
- * Returns an array of usb port paths with cameras. Port paths are the same
249
- * as in <b>gphoto2 --auto-detect</b> output. Assuming that if there are
250
- * cameras detected with long port paths, then the one with short port path
251
- * is a duplicate of one of the others.
252
- *
253
- * Examples:
254
- *
255
- * # with one camera connected
256
- * GPhoto2::Camera.ports #=> ["usb:"]
257
- * # with two cameras connected
258
- * GPhoto2::Camera.ports #=> ["usb:005,004", "usb:005,006"]
259
- *
260
- */
261
- static VALUE camera_class_ports(VALUE klass) {
262
- int i, camsTotal;
263
- GPContext *context;
264
- CameraAbilitiesList *abilList;
265
- GPPortInfoList *portInfoList;
266
- CameraList *camList;
267
- const char *pName = NULL;
268
- char *e = "";
269
- VALUE arr;
270
-
271
- context = gp_context_new();
272
- gp_result_check(gp_port_info_list_new(&portInfoList));
273
- gp_result_check(gp_port_info_list_load(portInfoList));
274
- gp_result_check(gp_abilities_list_new(&abilList));
275
- gp_result_check(gp_abilities_list_load(abilList, context));
276
- gp_result_check(gp_list_new(&camList));
277
-
278
- gp_result_check(gp_abilities_list_detect(abilList, portInfoList, camList, context));
279
-
280
- camsTotal = gp_result_check(gp_list_count(camList));
281
- arr = rb_ary_new();
282
- for(i = 0; i < camsTotal; i++) {
283
- gp_result_check(gp_list_get_value(camList, i, &pName));
284
- if ((camsTotal == 1) || (strlen(pName) > 4)) {
285
- rb_ary_push(arr, rb_str_new2(pName));
286
- }
287
- }
288
- gp_result_check(gp_list_free(camList));
289
- gp_result_check(gp_port_info_list_free(portInfoList));
290
- gp_result_check(gp_abilities_list_free(abilList));
291
- free(context);
292
- return arr;
293
- }
294
-
295
- /*
296
- * call-seq:
297
- * capture(config={}) => camera
298
- *
299
- * Sends command to camera to capture image with current or provided
300
- * configuration. Provided configuration is kept after capture.
301
- *
302
- * Examples:
303
- *
304
- * c = GPhoto2::Camera.new
305
- * c.capture
306
- * c.capture "exptime" => "0.010", "iso" => "400"
307
- *
308
- */
309
- static VALUE camera_capture(int argc, VALUE *argv, VALUE self) {
310
- GPhoto2Camera *c;
311
-
312
- Data_Get_Struct(self, GPhoto2Camera, c);
313
-
314
- if (argc == 1) {
315
- camera_config_merge(self, argv[0]);
316
- } else if (argc != 0) {
317
- rb_raise(rb_eArgError, "Wrong number of arguments (%d for 0 or 1)", argc);
318
- return Qnil;
319
- }
320
-
321
- gp_result_check(gp_camera_capture(c->camera, GP_CAPTURE_IMAGE, &(c->path), c->context));
322
- strcpy(c->virtFolder, c->path.folder);
323
- // printf("captured: %s/%s\n", c->path.folder, c->path.name);
324
- return self;
325
- }
326
-
327
- /*
328
- * call-seq:
329
- * save(options={}) => camera
330
- *
331
- * Downloads file from camera to hard drive.
332
- * Available options are:
333
- * * :file - Name of the file to download from camera. File is expected
334
- * to be found in current path. If this option is not specified, last
335
- * captured image is downloaded. If symbols <b>:first</b> or <b>:last</b>
336
- * are passed, the first or the last file from current camera path is
337
- * downloaded.
338
- * * :new_name - New file name to be used when saving file on hard drive.
339
- * If this option is not specified, camera file system filename is used.
340
- * * :to_folder - Folder path on hard drive to save downloaded image to.
341
- * * :type - Type of file to download from camera. Available types are
342
- * <b>:normal</b> (default) and <b>:preview</b>
343
- *
344
- * Examples:
345
- *
346
- * c = GPhoto2::Camera.new
347
- * c.capture.save :type => :preview, => Downloads preview of
348
- * :new_name => "PREVIEW.JPG" captured image
349
- * c.save :file => "DSC_0144.JPG", => Downloads specified file
350
- * :to_folder => "/home/user", to /home/user/xyz.gf.JPG
351
- * :new_name => "xyz.gf",
352
- *
353
- */
354
- static VALUE camera_save(int argc, VALUE *argv, VALUE self) {
355
- int i, count;
356
- int newName = -1;
357
- CameraFileType fileType = GP_FILE_TYPE_NORMAL;
358
- GPhoto2Camera *c;
359
- const char *fData, *key, *val, *name;
360
- char *fPath, *newNameStr, *pchNew, *pchSrc;
361
- char fName[100], cFileName[100], cFolderName[100];
362
- unsigned long int fSize;
363
- int fd;
364
- VALUE arr, hVal;
365
-
366
- Data_Get_Struct(self, GPhoto2Camera, c);
367
-
368
- strcpy(fName, "");
369
- strcpy(cFileName, c->path.name);
370
- strcpy(cFolderName, c->path.folder);
371
-
372
- gp_result_check(gp_filesystem_reset(c->camera->fs));
373
-
374
- switch(argc) {
375
- case 0:
376
- break;
377
- case 1:
378
- Check_Type(argv[0], T_HASH);
379
- arr = rb_funcall(argv[0], rb_intern("keys"), 0);
380
- for (i = 0; i < RARRAY(arr)->len; i++) {
381
- switch(TYPE(RARRAY(arr)->ptr[i])) {
382
- case T_STRING:
383
- key = RSTRING(RARRAY(arr)->ptr[i])->ptr;
384
- break;
385
- case T_SYMBOL:
386
- key = rb_id2name(rb_to_id(RARRAY(arr)->ptr[i]));
387
- break;
388
- default:
389
- rb_raise(rb_eTypeError, "Not valid key type");
390
- return Qnil;
391
- }
392
- if (strcmp(key, "to_folder") == 0) {
393
- fPath = RSTRING(rb_hash_aref(argv[0], RARRAY(arr)->ptr[i]))->ptr;
394
- if (strlen(fPath) > 0) {
395
- if (fPath[strlen(fPath)] == '/') {
396
- strcpy(fName, fPath);
397
- } else {
398
- strcpy(fName, fPath);
399
- strcat(fName, "/");
400
- }
401
- }
402
- } else if (strcmp(key, "new_name") == 0) {
403
- newNameStr = RSTRING(rb_hash_aref(argv[0], RARRAY(arr)->ptr[i]))->ptr;
404
- if (strlen(newNameStr) > 0) {
405
- newName = 0;
406
- }
407
- } else if (strcmp(key, "type") == 0) {
408
- hVal = rb_hash_aref(argv[0], RARRAY(arr)->ptr[i]);
409
- Check_Type(hVal, T_SYMBOL);
410
- val = rb_id2name(rb_to_id(hVal));
411
- if (strcmp(val, "normal") == 0) {
412
- fileType = GP_FILE_TYPE_NORMAL;
413
- } else if (strcmp(val, "preview") == 0) {
414
- fileType = GP_FILE_TYPE_PREVIEW;
415
- }
416
- } else if (strcmp(key, "file") == 0) {
417
- hVal = rb_hash_aref(argv[0], RARRAY(arr)->ptr[i]);
418
- switch(TYPE(hVal)) {
419
- case T_STRING:
420
- strcpy(cFolderName, c->virtFolder);
421
- strcpy(cFileName, RSTRING(hVal)->ptr);
422
- break;
423
- case T_SYMBOL:
424
- val = rb_id2name(rb_to_id(hVal));
425
- gp_result_check(gp_camera_folder_list_files(c->camera, c->virtFolder, c->list, c->context));
426
- if (strcmp(val, "first") == 0) {
427
- count = 0;
428
- } else if (strcmp(val, "last") == 0) {
429
- count = gp_result_check(gp_list_count(c->list)) - 1;
430
- } else {
431
- count = -1;
432
- }
433
- gp_result_check(gp_list_get_name(c->list, count, &name));
434
- strcpy(cFileName, name);
435
- break;
436
- default:
437
- rb_raise(rb_eTypeError, "Not valid value type");
438
- return Qnil;
439
- }
440
- }
441
- }
442
- break;
443
- default:
444
- rb_raise(rb_eArgError, "Wrong number of arguments (%d for 0 or 1)", argc);
445
- return Qnil;
446
- }
447
-
448
- gp_result_check(gp_camera_file_get(c->camera, cFolderName, cFileName, fileType, c->file, c->context));
449
- gp_result_check(gp_file_get_data_and_size(c->file, &fData, &fSize));
450
- if (newName == 0) {
451
- strcat(fName, newNameStr);
452
- pchNew = strrchr(newNameStr, '.');
453
- pchSrc = strrchr(cFileName, '.');
454
- if (pchNew == NULL) {
455
- strcat(fName, pchSrc);
456
- } else if (strcmp(pchNew, pchSrc) != 0) {
457
- strcat(fName, pchSrc);
458
- }
459
- } else {
460
- strcat(fName, cFileName);
461
- }
462
- fd = open(fName, O_CREAT | O_WRONLY, 0644);
463
- write(fd, fData, fSize);
464
- close(fd);
465
- return self;
466
- }
467
-
468
- /*
469
- * call-seq:
470
- * delete(options={}) => camera
471
- *
472
- * Deletes file from camera.
473
- * Available options are:
474
- * * :file - Name of the file to delete from camera. File is expected
475
- * to be found in current path. If this option is not specified, last
476
- * captured image is deleted.
477
- *
478
- * Examples:
479
- *
480
- * c = GPhoto2::Camera.new
481
- * c.capture.save.delete
482
- * c.delete :file => "DSC_0144.JPG"
483
- *
484
- */
485
- static VALUE camera_delete(int argc, VALUE *argv, VALUE self) {
486
- int i;
487
- GPhoto2Camera *c;
488
- const char *key;
489
- char cFileName[100], cFolderName[100];
490
- VALUE arr;
491
-
492
- Data_Get_Struct(self, GPhoto2Camera, c);
493
-
494
- strcpy(cFileName, c->path.name);
495
- strcpy(cFolderName, c->path.folder);
496
-
497
- switch(argc) {
498
- case 0:
499
- break;
500
- case 1:
501
- Check_Type(argv[0], T_HASH);
502
- arr = rb_funcall(argv[0], rb_intern("keys"), 0);
503
- for (i = 0; i < RARRAY(arr)->len; i++) {
504
- switch(TYPE(RARRAY(arr)->ptr[i])) {
505
- case T_STRING:
506
- key = RSTRING(RARRAY(arr)->ptr[i])->ptr;
507
- break;
508
- case T_SYMBOL:
509
- key = rb_id2name(rb_to_id(RARRAY(arr)->ptr[i]));
510
- break;
511
- default:
512
- rb_raise(rb_eTypeError, "Not valid key type");
513
- return Qnil;
514
- }
515
- if (strcmp(key, "file") == 0) {
516
- strcpy(cFolderName, c->virtFolder);
517
- strcpy(cFileName, RSTRING(rb_hash_aref(argv[0], RARRAY(arr)->ptr[i]))->ptr);
518
- }
519
- }
520
- break;
521
- default:
522
- rb_raise(rb_eArgError, "Wrong number of arguments (%d for 0 or 1)", argc);
523
- return Qnil;
524
- }
525
-
526
- gp_result_check(gp_filesystem_reset(c->camera->fs));
527
- gp_result_check(gp_camera_file_delete(c->camera, cFolderName, cFileName, c->context));
528
- return self;
529
- }
530
-
531
- /*
532
- * call-seq:
533
- * config => hash
534
- *
535
- * Returns cached hash of adjustable camera configuration with their values.
536
- *
537
- * Examples:
538
- *
539
- * c = GPhoto2::Camera.new
540
- * # with Nikon DSC D80
541
- * c.config.keys #=> ["capturetarget", "imgquality",
542
- * "imgsize", "whitebalance",
543
- * "f-number", "focallength",
544
- * "focusmode", "iso",
545
- * "exposurebiascompensation",
546
- * "exptime", "expprogram",
547
- * "capturemode", "focusmetermode",
548
- * "exposuremetermode", "flashmode",
549
- * "burstnumber", "accessmode",
550
- * "channel", "encryption"]
551
- *
552
- */
553
- static VALUE camera_get_config(VALUE self) {
554
- return rb_iv_get(self, "@configuration");
555
- }
556
-
557
- /*
558
- * call-seq:
559
- * config_merge(hash) => hash
560
- *
561
- * Adjusts camera configuration with given values.
562
- *
563
- * Examples:
564
- *
565
- * c = GPhoto2::Camera.new
566
- * # with Nikon DSC D80
567
- * c.config_merge "f-number" => "f/4", "exptime" => "0.010", "iso" => "200"
568
- *
569
- */
570
- static VALUE camera_config_merge(VALUE self, VALUE hash) {
571
- Check_Type(hash, T_HASH);
572
-
573
- int i;
574
- const char *key;
575
- GPhoto2Camera *c;
576
- CameraWidgetType widgettype;
577
- VALUE arr, cfgs, cfg_changed;
578
-
579
- Data_Get_Struct(self, GPhoto2Camera, c);
580
-
581
- arr = rb_funcall(hash, rb_intern("keys"), 0);
582
- cfgs = rb_iv_get(self, "@configuration");
583
- cfg_changed = rb_iv_get(self, "@configs_changed");
584
- for (i = 0; i < RARRAY(arr)->len; i++) {
585
- switch(TYPE(RARRAY(arr)->ptr[i])) {
586
- case T_STRING:
587
- key = RSTRING(RARRAY(arr)->ptr[i])->ptr;
588
- break;
589
- case T_SYMBOL:
590
- key = rb_id2name(rb_to_id(RARRAY(arr)->ptr[i]));
591
- break;
592
- default:
593
- rb_raise(rb_eTypeError, "Not valid key type");
594
- return Qnil;
595
- }
596
- if (TYPE(rb_funcall(cfgs, rb_intern("has_key?"), 1, rb_str_new2(key))) == T_TRUE) {
597
- gp_result_check(gp_widget_get_child_by_name(c->config, key, &(c->childConfig)));
598
- gp_result_check(gp_widget_get_type(c->childConfig, &widgettype));
599
- switch (widgettype) {
600
- case GP_WIDGET_RADIO:
601
- rb_ary_push(cfg_changed, rb_str_new2(key));
602
- setRadio(self, c, rb_hash_aref(hash, RARRAY(arr)->ptr[i]), 0);
603
- break;
604
- case GP_WIDGET_RANGE:
605
- rb_ary_push(cfg_changed, rb_str_new2(key));
606
- setRange(self, c, rb_hash_aref(hash, RARRAY(arr)->ptr[i]), 0);
607
- break;
608
- }
609
- }
610
- }
611
- saveConfigs(self, c);
612
- return cfgs;
613
- }
614
-
615
- /*
616
- * call-seq:
617
- * cam[cfg] => float or string
618
- * cam[cfg, :all] => array
619
- * cam[cfg, :type] => fixnum
620
- *
621
- * Returns current value of specified camera configuration. Configuration name
622
- * (cfg) can be string or symbol and must be in configs method returned array.
623
- * Configuration is cached in @configuration instance variable.
624
- *
625
- * Possible directives:
626
- * * <b>:no_cache</b> doesn't use cached configuration value
627
- * * <b>:all</b> returns an array of allowed values;
628
- * * <b>:type</b> returns one of available CONFIG_TYPE constats
629
- *
630
- * Examples:
631
- *
632
- * c = GPhoto2::Camera.new
633
- * # with Nikon DSC D80
634
- * c["f-number"] #=> "f/4.5"
635
- * c[:focallength] #=> 10.5
636
- * c[:focusmode, :all] #=> ["Manual", "AF-S", "AF-C", "AF-A"]
637
- * c[:exptime, :type] == GPhoto2::Camera::CONFIG_TYPE_RADIO
638
- * #=> true
639
- *
640
- */
641
- static VALUE camera_get_value(int argc, VALUE *argv, VALUE self) {
642
- const char *name;
643
- GPhoto2Camera *c;
644
- CameraWidgetType widgettype;
645
- VALUE str, dir, cfgs;
646
-
647
- switch (argc) {
648
- case 1:
649
- str = argv[0];
650
- break;
651
- case 2:
652
- str = argv[0];
653
- dir = argv[1];
654
- Check_Type(dir, T_SYMBOL);
655
- break;
656
- default:
657
- rb_raise(rb_eArgError, "Wrong number of arguments (%d for 1 or 2)", argc);
658
- return Qnil;
659
- }
660
-
661
- switch (TYPE(str)) {
662
- case T_STRING:
663
- name = RSTRING(str)->ptr;
664
- break;
665
- case T_SYMBOL:
666
- name = rb_id2name(rb_to_id(str));
667
- break;
668
- default:
669
- rb_raise(rb_eTypeError, "Not valid parameter type");
670
- return Qnil;
671
- }
672
-
673
- if (argc == 1) {
674
- return rb_hash_aref(rb_iv_get(self, "@configuration"), rb_str_new2(name));
675
- } else {
676
- Data_Get_Struct(self, GPhoto2Camera, c);
677
-
678
- gp_result_check(gp_widget_get_child_by_name(c->config, name, &(c->childConfig)));
679
- gp_result_check(gp_widget_get_type(c->childConfig, &widgettype));
680
- switch (widgettype) {
681
- case GP_WIDGET_RADIO:
682
- if (strcmp(rb_id2name(rb_to_id(dir)), "no_cache") == 0) {
683
- return getRadio(c->childConfig);
684
- } else if (strcmp(rb_id2name(rb_to_id(dir)), "all") == 0) {
685
- return listRadio(c->childConfig);
686
- } else if (strcmp(rb_id2name(rb_to_id(dir)), "type") == 0) {
687
- return INT2FIX(GP_WIDGET_RADIO);
688
- } else {
689
- rb_raise(rb_cGPhoto2ConfigurationError, "Unknown directive '%s'", rb_id2name(rb_to_id(dir)));
690
- return Qnil;
691
- }
692
- break;
693
- case GP_WIDGET_RANGE:
694
- if (strcmp(rb_id2name(rb_to_id(dir)), "no_cache") == 0) {
695
- return getRange(c->childConfig);
696
- } else if (strcmp(rb_id2name(rb_to_id(dir)), "all") == 0) {
697
- return listRange(c->childConfig);
698
- } else if (strcmp(rb_id2name(rb_to_id(dir)), "type") == 0) {
699
- return INT2FIX(GP_WIDGET_RANGE);
700
- } else {
701
- rb_raise(rb_cGPhoto2ConfigurationError, "Unknown directive '%s'", rb_id2name(rb_to_id(dir)));
702
- return Qnil;
703
- }
704
- break;
705
- default:
706
- rb_raise(rb_cGPhoto2ConfigurationError, "Not supported yet");
707
- return Qnil;
708
- }
709
- }
710
- }
711
-
712
- /*
713
- * call-seq:
714
- * cam[cfg] = value => float or string
715
- *
716
- * Sets specified camera configuration to specified value if value is allowed.
717
- *
718
- * Examples:
719
- *
720
- * c = GPhoto2::Camera.new
721
- * # with Nikon DSC D80
722
- * c["f-number"] = "f/4.5" #=> "f/4.5"
723
- * c[:focallength] = 10.5 #=> 10.5
724
- *
725
- */
726
- static VALUE camera_set_value(VALUE self, VALUE str, VALUE newVal) {
727
- const char *name;
728
- GPhoto2Camera *c;
729
- CameraWidgetType widgettype;
730
- VALUE cfg_changed;
731
-
732
- switch (TYPE(str)) {
733
- case T_STRING:
734
- name = RSTRING(str)->ptr;
735
- break;
736
- case T_SYMBOL:
737
- name = rb_id2name(rb_to_id(str));
738
- break;
739
- default:
740
- rb_raise(rb_eTypeError, "Not valid parameter type");
741
- return Qnil;
742
- }
743
-
744
- Data_Get_Struct(self, GPhoto2Camera, c);
745
-
746
- gp_result_check(gp_widget_get_child_by_name(c->config, name, &(c->childConfig)));
747
- gp_result_check(gp_widget_get_type(c->childConfig, &widgettype));
748
- switch (widgettype) {
749
- case GP_WIDGET_RADIO:
750
- cfg_changed = rb_iv_get(self, "@configs_changed");
751
- rb_ary_push(cfg_changed, rb_str_new2(name));
752
- return setRadio(self, c, newVal, 1);
753
- break;
754
- case GP_WIDGET_RANGE:
755
- cfg_changed = rb_iv_get(self, "@configs_changed");
756
- rb_ary_push(cfg_changed, rb_str_new2(name));
757
- return setRange(self, c, newVal, 1);
758
- break;
759
- default:
760
- rb_raise(rb_cGPhoto2ConfigurationError, "Cannot access this setting");
761
- return Qnil;
762
- }
763
- }
764
-
765
- /*
766
- * call-seq:
767
- * folder => string
768
- *
769
- * Returns current camera path. When image is captured, folder changes to
770
- * path where files are saved on camera.
771
- *
772
- * Examples:
773
- *
774
- * c = GPhoto2::Camera.new
775
- * # with Nikon DSC D80
776
- * c.folder #=> "/"
777
- * c.capture
778
- * c.folder #=> "/store_00010001/DCIM/100NCD80"
779
- *
780
- */
781
- static VALUE camera_folder(VALUE self) {
782
- GPhoto2Camera *c;
783
-
784
- Data_Get_Struct(self, GPhoto2Camera, c);
785
-
786
- return rb_str_new2(c->virtFolder);
787
- }
788
-
789
- /*
790
- * call-seq:
791
- * subfolders => array
792
- *
793
- * Returns an array of subfolder names in current camera path.
794
- *
795
- * Examples:
796
- *
797
- * c = GPhoto2::Camera.new
798
- * # with Nikon DSC D80
799
- * c.folder #=> "/"
800
- * c.subfolders #=> ["special", "store_00010001"]
801
- *
802
- */
803
- static VALUE camera_subfolders(VALUE self) {
804
- int i, count;
805
- const char *name;
806
- GPhoto2Camera *c;
807
- VALUE arr;
808
-
809
- Data_Get_Struct(self, GPhoto2Camera, c);
810
-
811
- gp_result_check(gp_camera_folder_list_folders(c->camera, c->virtFolder, c->list, c->context));
812
- count = gp_result_check(gp_list_count(c->list));
813
- arr = rb_ary_new();
814
- for (i = 0; i < count; i++) {
815
- gp_result_check(gp_list_get_name(c->list, i, &name));
816
- rb_ary_push(arr, rb_str_new2(name));
817
- }
818
- return arr;
819
- }
820
-
821
- /*
822
- * call-seq:
823
- * files => array
824
- *
825
- * Returns an array of file names in current camera path.
826
- *
827
- * Examples:
828
- *
829
- * c = GPhoto2::Camera.new
830
- * # with Nikon DSC D80
831
- * c.folder #=> "/"
832
- * c.files #=> []
833
- * c.capture
834
- * c.files #=> ["DSC_0001.JPG", "DSC_0002.JPG",
835
- * "DSC_0003.JPG", ... ]
836
- *
837
- */
838
- static VALUE camera_files(VALUE self) {
839
- int i, count;
840
- const char *name;
841
- GPhoto2Camera *c;
842
- VALUE arr;
843
-
844
- Data_Get_Struct(self, GPhoto2Camera, c);
845
-
846
- gp_result_check(gp_filesystem_reset(c->camera->fs));
847
- gp_result_check(gp_camera_folder_list_files(c->camera, c->virtFolder, c->list, c->context));
848
- count = gp_result_check(gp_list_count(c->list));
849
- arr = rb_ary_new();
850
- for (i = 0; i < count; i++) {
851
- gp_result_check(gp_list_get_name(c->list, i, &name));
852
- rb_ary_push(arr, rb_str_new2(name));
853
- }
854
- return arr;
855
- }
856
-
857
- /*
858
- * call-seq:
859
- * folder_up => camera
860
- *
861
- * Changes current camera path one level up.
862
- *
863
- * Examples:
864
- *
865
- * c = GPhoto2::Camera.new
866
- * # with Nikon DSC D80
867
- * c.folder #=> "/"
868
- * c.capture
869
- * c.folder #=> "/store_00010001/DCIM/100NCD80"
870
- * c.folder_up
871
- * c.folder #=> "/store_00010001/DCIM"
872
- * c.folder_up.folder_up #=> "/"
873
- *
874
- */
875
- static VALUE camera_folder_up(VALUE self) {
876
- char *pch;
877
- GPhoto2Camera *c;
878
-
879
- Data_Get_Struct(self, GPhoto2Camera, c);
880
-
881
- pch = strrchr(c->virtFolder, '/');
882
- if ((pch - c->virtFolder) == 0) {
883
- c->virtFolder[1] = '\0';
884
- } else {
885
- c->virtFolder[pch - c->virtFolder] = '\0';
886
- }
887
-
888
- return self;
889
- }
890
-
891
- /*
892
- * call-seq:
893
- * folder_down(name) => camera
894
- *
895
- * Changes current camera path one level down into subfolder with
896
- * specified name.
897
- *
898
- * Examples:
899
- *
900
- * c = GPhoto2::Camera.new
901
- * # with Nikon DSC D80
902
- * c.folder #=> "/"
903
- * c.folder_down "store_00010001"
904
- * c.folder #=> "/store_00010001"
905
- * c.folder_down("DCIM").folder_down("100NCD80")
906
- * c.folder #=> "/store_00010001/DCIM/100NCD80"
907
- *
908
- */
909
- static VALUE camera_folder_down(VALUE self, VALUE folder) {
910
- Check_Type(folder, T_STRING);
911
-
912
- const char *name;
913
- int index;
914
- GPhoto2Camera *c;
915
-
916
- Data_Get_Struct(self, GPhoto2Camera, c);
917
-
918
- name = RSTRING(folder)->ptr;
919
- gp_result_check(gp_camera_folder_list_folders(c->camera, c->virtFolder, c->list, c->context));
920
- gp_result_check(gp_list_find_by_name(c->list, &index, name));
921
- if (strlen(c->virtFolder) > 1) {
922
- strcat(c->virtFolder, "/");
923
- }
924
- strcat(c->virtFolder, name);
925
- return self;
926
- }
927
-
928
- /*
929
- * call-seq:
930
- * wait(timeout=2000) => camera event
931
- *
932
- * Waits for an event from camera for specified amount of milliseconds.
933
- * Returns an instance of GPhoto2::CameraEvent. When capturing image manually
934
- * with camera connected through USB, images are not saved on memory card
935
- * until you call this method. During tests EVENT_TYPE_FILE_ADDED event
936
- * was always followed by EVENT_TYPE_UNKNOWN. So in the case of
937
- * EVENT_TYPE_FILE_ADDED or EVENT_TYPE_FOLDER_ADDED, an extra call is made
938
- * with 100ms timeout which result is ignored.
939
- *
940
- * When image is captured manually and then event is caught, camera virtual
941
- * folder is changed to the one where files are saved.
942
- *
943
- * Examples:
944
- *
945
- * c = GPhoto2::Camera.new
946
- * # capture the image manually
947
- * evt = c.wait
948
- * evt.type #=> "file added"
949
- * evt.type == GPhoto2::CameraEvent::EVENT_TYPE_FILE_ADDED
950
- * #=> true
951
- * evt.file #=> "DSC_0384.JPG"
952
- *
953
- * # do nothing
954
- * c.wait(1).type #=> "timeout"
955
- */
956
- static VALUE camera_wait(int argc, VALUE *argv, VALUE self) {
957
- GPhoto2Camera *c;
958
- GPhoto2CameraEvent *ce;
959
- CameraEventType fakeType;
960
- void *evtData, *fakeData;
961
- int to;
962
-
963
- switch (argc) {
964
- case 0:
965
- to = 2000;
966
- break;
967
- case 1:
968
- to = FIX2INT(rb_funcall(argv[0], rb_intern("to_i"), 0));
969
- break;
970
- default:
971
- rb_raise(rb_eArgError, "Wrong number of arguments (%d for 0 or 1)", argc);
972
- return Qnil;
973
- }
974
-
975
- Data_Get_Struct(self, GPhoto2Camera, c);
976
- ce = (GPhoto2CameraEvent*) malloc(sizeof(GPhoto2CameraEvent));
977
-
978
- gp_result_check(gp_camera_wait_for_event(c->camera, to, &(ce->type), &evtData, c->context));
979
-
980
- switch (ce->type) {
981
- case GP_EVENT_FILE_ADDED:
982
- case GP_EVENT_FOLDER_ADDED:
983
- ce->path = (CameraFilePath*)evtData;
984
- strcpy(c->virtFolder, ce->path->folder);
985
- gp_result_check(gp_camera_wait_for_event(c->camera, 100, &fakeType, &fakeData, c->context));
986
- break;
987
- }
988
- return Data_Wrap_Struct(rb_cGPhoto2CameraEvent, camera_event_mark, camera_event_free, ce);
989
- }
990
-
991
- /*
992
- * call-seq:
993
- * type => string
994
- *
995
- * Returns type of event. Can be compared to EVENT_TYPE class constants
996
- *
997
- * Examples:
998
- *
999
- * c = GPhoto2::Camera.new
1000
- * # capture the image manually
1001
- * evt = c.wait
1002
- * evt.type #=> "file added"
1003
- * evt.type == GPhoto2::CameraEvent::EVENT_TYPE_FILE_ADDED
1004
- * #=> true
1005
- * evt.file #=> "DSC_0384.JPG"
1006
- *
1007
- * # do nothing
1008
- * c.wait(1).type #=> "timeout"
1009
- */
1010
- static VALUE camera_event_type(VALUE self) {
1011
- GPhoto2CameraEvent *ce;
1012
-
1013
- Data_Get_Struct(self, GPhoto2CameraEvent, ce);
1014
-
1015
- switch (ce->type) {
1016
- case GP_EVENT_FILE_ADDED:
1017
- return EVENT_FILE_ADDED;
1018
- case GP_EVENT_FOLDER_ADDED:
1019
- return EVENT_FOLDER_ADDED;
1020
- case GP_EVENT_TIMEOUT:
1021
- return EVENT_TIMEOUT;
1022
- case GP_EVENT_UNKNOWN:
1023
- return EVENT_UNKNOWN;
1024
- default:
1025
- return Qnil;
1026
- }
1027
- }
1028
-
1029
- /*
1030
- * call-seq:
1031
- * file => string or nil
1032
- *
1033
- * Returns file name of manually captured image. Only applies to
1034
- * EVENT_TYPE_FILE_ADDED event.
1035
- *
1036
- * Examples:
1037
- *
1038
- * c = GPhoto2::Camera.new
1039
- * # capture the image manually
1040
- * evt = c.wait
1041
- * evt.type #=> "file added"
1042
- * evt.type == GPhoto2::CameraEvent::EVENT_TYPE_FILE_ADDED
1043
- * #=> true
1044
- * evt.file #=> "DSC_0384.JPG"
1045
- *
1046
- * # do nothing
1047
- * c.wait(1).type #=> "timeout"
1048
- */
1049
- static VALUE camera_event_file(VALUE self) {
1050
- GPhoto2CameraEvent *ce;
1051
-
1052
- Data_Get_Struct(self, GPhoto2CameraEvent, ce);
1053
-
1054
- if (ce->type == GP_EVENT_FILE_ADDED) {
1055
- return rb_str_new2(ce->path->name);
1056
- } else {
1057
- return Qnil;
1058
- }
1059
- }
29
+ #include "gphoto2camera_event.h"
30
+ #include "gphoto2camera_utilities.h"
31
+ #include "gphoto2camera.h"
1060
32
 
1061
33
  void Init_gphoto4ruby() {
1062
34
  /*
@@ -1086,7 +58,9 @@ void Init_gphoto4ruby() {
1086
58
  rb_cGPhoto2ConfigurationError = rb_define_class_under(rb_mGPhoto2, "ConfigurationError", rb_eStandardError);
1087
59
 
1088
60
  rb_define_const(rb_cGPhoto2Camera, "CONFIG_TYPE_RADIO", INT2FIX(GP_WIDGET_RADIO));
61
+ rb_define_const(rb_cGPhoto2Camera, "CONFIG_TYPE_TEXT", INT2FIX(GP_WIDGET_TEXT));
1089
62
  rb_define_const(rb_cGPhoto2Camera, "CONFIG_TYPE_RANGE", INT2FIX(GP_WIDGET_RANGE));
63
+ rb_define_const(rb_cGPhoto2Camera, "CONFIG_TYPE_TOGGLE", INT2FIX(GP_WIDGET_TOGGLE));
1090
64
 
1091
65
  rb_define_const(rb_cGPhoto2CameraEvent, "EVENT_TYPE_UNKNOWN", EVENT_UNKNOWN);
1092
66
  rb_define_const(rb_cGPhoto2CameraEvent, "EVENT_TYPE_TIMEOUT", EVENT_TIMEOUT);
@@ -1094,23 +68,23 @@ void Init_gphoto4ruby() {
1094
68
  rb_define_const(rb_cGPhoto2CameraEvent, "EVENT_TYPE_FOLDER_ADDED", EVENT_FOLDER_ADDED);
1095
69
 
1096
70
  rb_define_alloc_func(rb_cGPhoto2Camera, camera_allocate);
1097
- rb_define_module_function(rb_cGPhoto2Camera, "ports", camera_class_ports, 0);
1098
- rb_define_method(rb_cGPhoto2Camera, "initialize", camera_initialize, -1);
1099
- rb_define_method(rb_cGPhoto2Camera, "config", camera_get_config, 0);
1100
- rb_define_method(rb_cGPhoto2Camera, "config_merge", camera_config_merge, 1);
1101
- rb_define_method(rb_cGPhoto2Camera, "[]", camera_get_value, -1);
1102
- rb_define_method(rb_cGPhoto2Camera, "[]=", camera_set_value, 2);
1103
- rb_define_method(rb_cGPhoto2Camera, "capture", camera_capture, -1);
1104
- rb_define_method(rb_cGPhoto2Camera, "save", camera_save, -1);
1105
- rb_define_method(rb_cGPhoto2Camera, "delete", camera_delete, -1);
1106
- rb_define_method(rb_cGPhoto2Camera, "folder", camera_folder, 0);
1107
- rb_define_method(rb_cGPhoto2Camera, "subfolders", camera_subfolders, 0);
1108
- rb_define_method(rb_cGPhoto2Camera, "files", camera_files, 0);
1109
- rb_define_method(rb_cGPhoto2Camera, "folder_up", camera_folder_up, 0);
1110
- rb_define_method(rb_cGPhoto2Camera, "folder_down", camera_folder_down, 1);
1111
- rb_define_method(rb_cGPhoto2Camera, "wait", camera_wait, -1);
1112
-
1113
- rb_define_method(rb_cGPhoto2CameraEvent, "type", camera_event_type, 0);
1114
- rb_define_method(rb_cGPhoto2CameraEvent, "file", camera_event_file, 0);
71
+ rb_define_module_function(rb_cGPhoto2Camera, "ports", camera_class_ports, 0); /* in gphoto2camera.c */
72
+ rb_define_method(rb_cGPhoto2Camera, "initialize", camera_initialize, -1); /* in gphoto2camera.c */
73
+ rb_define_method(rb_cGPhoto2Camera, "config", camera_get_config, 0); /* in gphoto2camera.c */
74
+ rb_define_method(rb_cGPhoto2Camera, "config_merge", camera_config_merge, 1); /* in gphoto2camera.c */
75
+ rb_define_method(rb_cGPhoto2Camera, "[]", camera_get_value, -1); /* in gphoto2camera.c */
76
+ rb_define_method(rb_cGPhoto2Camera, "[]=", camera_set_value, 2); /* in gphoto2camera.c */
77
+ rb_define_method(rb_cGPhoto2Camera, "capture", camera_capture, -1); /* in gphoto2camera.c */
78
+ rb_define_method(rb_cGPhoto2Camera, "save", camera_save, -1); /* in gphoto2camera.c */
79
+ rb_define_method(rb_cGPhoto2Camera, "delete", camera_delete, -1); /* in gphoto2camera.c */
80
+ rb_define_method(rb_cGPhoto2Camera, "folder", camera_folder, 0); /* in gphoto2camera.c */
81
+ rb_define_method(rb_cGPhoto2Camera, "subfolders", camera_subfolders, 0); /* in gphoto2camera.c */
82
+ rb_define_method(rb_cGPhoto2Camera, "files", camera_files, 0); /* in gphoto2camera.c */
83
+ rb_define_method(rb_cGPhoto2Camera, "folder_up", camera_folder_up, 0); /* in gphoto2camera.c */
84
+ rb_define_method(rb_cGPhoto2Camera, "folder_down", camera_folder_down, 1); /* in gphoto2camera.c */
85
+ rb_define_method(rb_cGPhoto2Camera, "wait", camera_wait, -1); /* in gphoto2camera.c */
86
+
87
+ rb_define_method(rb_cGPhoto2CameraEvent, "type", camera_event_type, 0); /* in gphoto2camera_event.c */
88
+ rb_define_method(rb_cGPhoto2CameraEvent, "file", camera_event_file, 0); /* in gphoto2camera_event.c */
1115
89
  }
1116
90