gphoto4ruby 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,13 @@
1
+ == 0.4.2
2
+
3
+ Pulled changes from Tallak Tveide
4
+
5
+ * Added pthread to keep camera alive when library is available
6
+ * Added several question mark methods (has_config?, has_image_capture? and
7
+ has_preview?) based on gphoto2 camera abilities
8
+ * Added model_name
9
+ * Added dispose method that allows to reuse same code and reinitialize camera
10
+
1
11
  == 0.4.1
2
12
 
3
13
  * Fix for canon cameras to keep "capture=on" between ruby calls. Though it shows
data/README.rdoc CHANGED
@@ -101,6 +101,11 @@ connected through usb in PTP mode and Canon EOS 450D.
101
101
  # it from camera
102
102
  cams.first.capture.save.delete
103
103
  end
104
+
105
+
106
+ On supported systems, instanciating a camera will start a thread that
107
+ prevents the camera from posering off automatically.
108
+
104
109
  == Contact
105
110
 
106
111
  neq4 company:: http://neq4.com
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.4.2
data/example.rb CHANGED
@@ -8,6 +8,7 @@ if ports.any?
8
8
  ports.each do |port|
9
9
  c = GPhoto2::Camera.new(port)
10
10
  puts "camera in port: " + port
11
+ puts 'Model: ' + c.model_name
11
12
  c["capture"] = true if c.config.has_key? "capture" # canon? :)
12
13
  c.config(:no_cache).each do |key, value|
13
14
  puts key + " value is: " + value.to_s
data/ext/gphoto2camera.c CHANGED
@@ -20,8 +20,36 @@
20
20
  *
21
21
  */
22
22
 
23
+ /* CAMERA TIMEOUT FUNCTIONALITY COPIED FROM libgphoto2 */
24
+ /*
25
+ * Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
26
+ *
27
+ * This library is free software; you can redistribute it and/or
28
+ * modify it under the terms of the GNU Lesser General Public
29
+ * License as published by the Free Software Foundation; either
30
+ * version 2 of the License, or (at your option) any later version.
31
+ *
32
+ * This library is distributed in the hope that it will be useful,
33
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35
+ * Lesser General Public License for more details.
36
+ *
37
+ * You should have received a copy of the GNU Lesser General Public
38
+ * License along with this library; if not, write to the
39
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
40
+ * Boston, MA 02111-1307, USA.
41
+ */
42
+
43
+
44
+
23
45
  #include "gphoto2camera.h"
24
46
 
47
+ #ifdef HAVE_PTHREAD
48
+ #include <time.h>
49
+ #include <pthread.h>
50
+ #endif
51
+
52
+
25
53
  VALUE rb_mGPhoto2;
26
54
  VALUE rb_cGPhoto2Camera;
27
55
 
@@ -49,10 +77,74 @@ VALUE rb_cGPhoto2ConfigurationError;
49
77
  } \
50
78
  }
51
79
 
80
+
81
+
82
+ #ifdef HAVE_PTHREAD
83
+ static void thread_cleanup_func (void *data) {
84
+ ThreadData *td = data;
85
+ free (td);
86
+ }
87
+
88
+ static void * thread_func (void *data) {
89
+ ThreadData *td = data;
90
+ time_t t, last;
91
+ int dummy;
92
+ struct timespec interval, remainder;
93
+ double diff;
94
+
95
+ pthread_cleanup_push (thread_cleanup_func, td);
96
+
97
+ last = time (NULL);
98
+ while (1) {
99
+ /* Sleep first to avoid loop using all CPU */
100
+ t = time (NULL);
101
+ interval.tv_sec = td-> timeout - (t - last);
102
+ interval.tv_nsec = 0;
103
+ pthread_setcanceltype(PTHREAD_CANCEL_ENABLE, &dummy);
104
+ nanosleep(*interval, *remainder);
105
+ pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &dummy);
106
+
107
+ t = time (NULL);
108
+ if (t - last > td->timeout) {
109
+ td->func (td->camera, NULL);
110
+ last = t;
111
+ }
112
+ pthread_testcancel ();
113
+ }
114
+ pthread_cleanup_pop (1);
115
+ }
116
+
117
+ static unsigned int start_timeout_func (Camera *camera, unsigned int timeout, CameraTimeoutFunc func, void __unused__ *data) {
118
+ pthread_t tid;
119
+ ThreadData *td;
120
+
121
+ td = malloc (sizeof (ThreadData));
122
+ if (!td)
123
+ return 0;
124
+ memset (td, 0, sizeof (ThreadData));
125
+ td->camera = camera;
126
+ td->timeout = timeout;
127
+ td->func = func;
128
+
129
+ pthread_create (&tid, NULL, thread_func, td);
130
+
131
+ return (tid);
132
+ }
133
+
134
+ static void stop_timeout_func (Camera __unused__ *camera, unsigned int id, void __unused__ *data) {
135
+ pthread_t tid = id;
136
+ pthread_cancel (tid);
137
+ pthread_join (tid, NULL);
138
+ }
139
+
140
+ #endif
141
+
142
+
52
143
  void camera_mark(GPhoto2Camera *c) {
53
144
  }
54
145
 
55
146
  void camera_free(GPhoto2Camera *c) {
147
+ if (!c->disposed) {
56
148
  gp_result_check(gp_camera_exit(c->camera, c->context));
57
149
  gp_result_check(gp_widget_free(c->config));
58
150
  gp_result_check(gp_camera_unref(c->camera));
@@ -60,7 +152,8 @@ void camera_free(GPhoto2Camera *c) {
60
152
  free(c->virtFolder);
61
153
  free(c->lastName);
62
154
  free(c->context);
63
- free(c);
155
+ }
156
+ free(c);
64
157
  }
65
158
 
66
159
  VALUE camera_allocate(VALUE klass) {
@@ -71,9 +164,11 @@ VALUE camera_allocate(VALUE klass) {
71
164
  strcpy(c->virtFolder, "/");
72
165
  c->lastName[0] = '\0';
73
166
  c->context = gp_context_new();
167
+ c->disposed = 0;
74
168
  gp_result_check(gp_camera_new(&(c->camera)));
75
169
  gp_result_check(gp_camera_get_config(c->camera, &(c->config), c->context));
76
170
  gp_result_check(gp_camera_ref(c->camera));
171
+ gp_result_check(gp_camera_get_abilities (c->camera, &((*c).abilities)));
77
172
  return Data_Wrap_Struct(klass, camera_mark, camera_free, c);
78
173
  }
79
174
 
@@ -122,10 +217,53 @@ VALUE camera_initialize(int argc, VALUE *argv, VALUE self) {
122
217
  populateWithConfigs(c->config, cfgs);
123
218
  rb_iv_set(self, "@configuration", cfgs);
124
219
  rb_iv_set(self, "@configs_changed", rb_ary_new());
220
+
221
+ #ifdef HAVE_PTHREAD
222
+ gp_camera_set_timeout_funcs (c->camera, start_timeout_func, stop_timeout_func, NULL);
223
+ #endif
224
+
225
+
125
226
 
126
227
  return self;
127
228
  }
128
229
 
230
+
231
+ /*
232
+ * call-seq:
233
+ * dispose => nil
234
+ *
235
+ * Releases resources aquired by the Camera class so that is will be possible
236
+ * to connect to the camera again even before Ruby garbage collection has
237
+ * released the Camera from memory
238
+ *
239
+ * Examples:
240
+ *
241
+ * c = GPhoto2::Camera.new
242
+ * begin
243
+ * c.capture
244
+ * ensure
245
+ * c.dispose # if capture failed, this code may run again in the same process
246
+ * end
247
+ *
248
+ */
249
+ VALUE camera_dispose(VALUE self) {
250
+ GPhoto2Camera *c;
251
+ Data_Get_Struct(self, GPhoto2Camera, c);
252
+ if (!c->disposed) {
253
+ gp_result_check(gp_camera_exit(c->camera, c->context));
254
+ gp_result_check(gp_widget_free(c->config));
255
+ gp_result_check(gp_camera_unref(c->camera));
256
+ gp_result_check(gp_camera_free(c->camera));
257
+ free(c->virtFolder);
258
+ free(c->lastName);
259
+ free(c->context);
260
+ c->disposed = -1;
261
+ return Qtrue;
262
+ } else {
263
+ return Qfalse;
264
+ }
265
+ }
266
+
129
267
  /*
130
268
  * call-seq:
131
269
  * GPhoto2::Camera.ports => array
@@ -211,6 +349,7 @@ VALUE camera_capture(int argc, VALUE *argv, VALUE self) {
211
349
  CameraFilePath path;
212
350
 
213
351
  Data_Get_Struct(self, GPhoto2Camera, c);
352
+ check_disposed(c);
214
353
 
215
354
  if (argc == 1) {
216
355
  camera_config_merge(self, argv[0]);
@@ -271,6 +410,7 @@ VALUE camera_save(int argc, VALUE *argv, VALUE self) {
271
410
  VALUE arr, hVal;
272
411
 
273
412
  Data_Get_Struct(self, GPhoto2Camera, c);
413
+ check_disposed(c);
274
414
 
275
415
  gp_list_new(&list);
276
416
 
@@ -372,19 +512,34 @@ VALUE camera_save(int argc, VALUE *argv, VALUE self) {
372
512
  strcat(fName, newNameStr);
373
513
  pchNew = strrchr(newNameStr, '.');
374
514
  pchSrc = strrchr(cFileName, '.');
515
+ if (fileType == GP_FILE_TYPE_PREVIEW) {
516
+ pchSrc = ".JPG"; /* previews are always jpeg, even if original is RAW/TIF/etc */
517
+ }
375
518
  if (pchNew == NULL) {
376
519
  strcat(fName, pchSrc);
377
- } else if (strcmp(pchNew, pchSrc) != 0) {
520
+ } else if (strcasecmp(pchNew, pchSrc) != 0) {
378
521
  strcat(fName, pchSrc);
379
522
  }
380
523
  } else {
381
- strcat(fName, cFileName);
524
+ pchSrc = strrchr(cFileName, '.');
525
+ if (fileType == GP_FILE_TYPE_PREVIEW && pchSrc) {
526
+ strncat(fName, cFileName, pchSrc - cFileName);
527
+ strcat(fName, ".JPG");
528
+ } else {
529
+ strcat(fName, cFileName);
530
+ }
382
531
  }
383
532
  } else {
384
- strcat(fName, cFileName);
533
+ pchSrc = strrchr(cFileName, '.');
534
+ if (fileType == GP_FILE_TYPE_PREVIEW && pchSrc) {
535
+ strncat(fName, cFileName, pchSrc - cFileName);
536
+ strcat(fName, ".JPG");
537
+ } else {
538
+ strcat(fName, cFileName);
539
+ }
385
540
  }
386
- fd = open(fName, O_CREAT | O_WRONLY, 0644);
387
- retVal = write(fd, fData, fSize);
541
+ fd = open(fName, O_CREAT | O_WRONLY, 0644);
542
+ retVal = write(fd, fData, fSize);
388
543
  close(fd);
389
544
  gp_file_free(file);
390
545
  gp_list_free(list);
@@ -425,6 +580,7 @@ VALUE camera_delete(int argc, VALUE *argv, VALUE self) {
425
580
  VALUE arr;
426
581
 
427
582
  Data_Get_Struct(self, GPhoto2Camera, c);
583
+ check_disposed(c);
428
584
 
429
585
  gp_list_new(&list);
430
586
 
@@ -532,6 +688,7 @@ VALUE camera_get_config(int argc, VALUE *argv, VALUE self) {
532
688
  case 1:
533
689
  Check_Type(argv[0], T_SYMBOL);
534
690
  Data_Get_Struct(self, GPhoto2Camera, c);
691
+ check_disposed(c);
535
692
 
536
693
  if (strcmp(rb_id2name(rb_to_id(argv[0])), "no_cache") == 0) {
537
694
  gp_widget_free(c->config);
@@ -573,6 +730,7 @@ VALUE camera_config_merge(VALUE self, VALUE hash) {
573
730
  VALUE arr, cfgs, cfg_changed;
574
731
 
575
732
  Data_Get_Struct(self, GPhoto2Camera, c);
733
+ check_disposed(c);
576
734
 
577
735
  arr = rb_funcall(hash, rb_intern("keys"), 0);
578
736
  cfgs = rb_iv_get(self, "@configuration");
@@ -677,6 +835,7 @@ VALUE camera_get_value(int argc, VALUE *argv, VALUE self) {
677
835
  dir = argv[1];
678
836
  Check_Type(dir, T_SYMBOL);
679
837
  Data_Get_Struct(self, GPhoto2Camera, c);
838
+ check_disposed(c);
680
839
 
681
840
  if (strcmp(rb_id2name(rb_to_id(dir)), "no_cache") == 0) {
682
841
  gp_widget_free(c->config);
@@ -803,6 +962,7 @@ VALUE camera_set_value(VALUE self, VALUE str, VALUE newVal) {
803
962
  }
804
963
 
805
964
  Data_Get_Struct(self, GPhoto2Camera, c);
965
+ check_disposed(c);
806
966
 
807
967
  gp_result_check(gp_widget_get_child_by_name(c->config, name, &(c->childConfig)));
808
968
  gp_result_check(gp_widget_get_type(c->childConfig, &widgettype));
@@ -838,6 +998,65 @@ VALUE camera_set_value(VALUE self, VALUE str, VALUE newVal) {
838
998
  }
839
999
  }
840
1000
 
1001
+
1002
+
1003
+ /*
1004
+ * call-seq:
1005
+ * model_name => string
1006
+ *
1007
+ * Returns the model name of the camera
1008
+ *
1009
+ */
1010
+ VALUE camera_model_name(VALUE self) {
1011
+ GPhoto2Camera *c;
1012
+ Data_Get_Struct(self, GPhoto2Camera, c);
1013
+ check_disposed(c);
1014
+ return rb_str_new2((*c).abilities.model);
1015
+ }
1016
+
1017
+ /*
1018
+ * call-seq:
1019
+ * has_image_capture? => bool
1020
+ *
1021
+ * Returns true if the camera is capable of image capture
1022
+ *
1023
+ */
1024
+ VALUE camera_has_image_capture(VALUE self) {
1025
+ GPhoto2Camera *c;
1026
+ Data_Get_Struct(self, GPhoto2Camera, c);
1027
+ check_disposed(c);
1028
+ return ((*c).abilities.operations & GP_OPERATION_CAPTURE_IMAGE) ? Qtrue : Qfalse;
1029
+ }
1030
+
1031
+ /*
1032
+ * call-seq:
1033
+ * has_preview? => bool
1034
+ *
1035
+ * Returns true if the camera is capable of generatig image previews
1036
+ *
1037
+ */
1038
+ VALUE camera_has_preview(VALUE self) {
1039
+ GPhoto2Camera *c;
1040
+ Data_Get_Struct(self, GPhoto2Camera, c);
1041
+ check_disposed(c);
1042
+ return ((*c).abilities.operations & GP_OPERATION_CAPTURE_PREVIEW) ? Qtrue : Qfalse;
1043
+ }
1044
+
1045
+ /*
1046
+ * call-seq:
1047
+ * has_config? => bool
1048
+ *
1049
+ * Returns true if the camera has any configuration values
1050
+ *
1051
+ */
1052
+ VALUE camera_has_config(VALUE self) {
1053
+ GPhoto2Camera *c;
1054
+ Data_Get_Struct(self, GPhoto2Camera, c);
1055
+ check_disposed(c);
1056
+ return ((*c).abilities.operations & GP_OPERATION_CONFIG) ? Qtrue : Qfalse;
1057
+ }
1058
+
1059
+
841
1060
  /*
842
1061
  * call-seq:
843
1062
  * folder => string
@@ -858,6 +1077,7 @@ VALUE camera_folder(VALUE self) {
858
1077
  GPhoto2Camera *c;
859
1078
 
860
1079
  Data_Get_Struct(self, GPhoto2Camera, c);
1080
+ check_disposed(c);
861
1081
 
862
1082
  return rb_str_new2(c->virtFolder);
863
1083
  }
@@ -887,6 +1107,7 @@ VALUE camera_subfolders(VALUE self) {
887
1107
  VALUE arr;
888
1108
 
889
1109
  Data_Get_Struct(self, GPhoto2Camera, c);
1110
+ check_disposed(c);
890
1111
 
891
1112
  gp_list_new(&list);
892
1113
 
@@ -940,6 +1161,7 @@ VALUE camera_files(int argc, VALUE *argv, VALUE self) {
940
1161
  }
941
1162
 
942
1163
  Data_Get_Struct(self, GPhoto2Camera, c);
1164
+ check_disposed(c);
943
1165
 
944
1166
  gp_list_new(&list);
945
1167
 
@@ -985,6 +1207,7 @@ VALUE camera_files_count(VALUE self) {
985
1207
  CameraList *list;
986
1208
 
987
1209
  Data_Get_Struct(self, GPhoto2Camera, c);
1210
+ check_disposed(c);
988
1211
 
989
1212
  gp_list_new(&list);
990
1213
 
@@ -1020,6 +1243,7 @@ VALUE camera_folder_up(VALUE self) {
1020
1243
  GPhoto2Camera *c;
1021
1244
 
1022
1245
  Data_Get_Struct(self, GPhoto2Camera, c);
1246
+ check_disposed(c);
1023
1247
 
1024
1248
  pch = strrchr(c->virtFolder, '/');
1025
1249
  if ((pch - c->virtFolder) == 0) {
@@ -1060,6 +1284,7 @@ VALUE camera_folder_down(VALUE self, VALUE folder) {
1060
1284
  GPhoto2Camera *c;
1061
1285
 
1062
1286
  Data_Get_Struct(self, GPhoto2Camera, c);
1287
+ check_disposed(c);
1063
1288
 
1064
1289
  gp_list_new(&list);
1065
1290
 
@@ -1094,6 +1319,7 @@ VALUE camera_create_folder(VALUE self, VALUE folder) {
1094
1319
  GPhoto2Camera *c;
1095
1320
 
1096
1321
  Data_Get_Struct(self, GPhoto2Camera, c);
1322
+ check_disposed(c);
1097
1323
 
1098
1324
  name = RSTRING_PTR(folder);
1099
1325
  gp_result_check(gp_camera_folder_make_dir(c->camera, c->virtFolder, name, c->context));
@@ -1156,6 +1382,7 @@ VALUE camera_wait(int argc, VALUE *argv, VALUE self) {
1156
1382
  }
1157
1383
 
1158
1384
  Data_Get_Struct(self, GPhoto2Camera, c);
1385
+ check_disposed(c);
1159
1386
  ce = (GPhoto2CameraEvent*) ALLOC(GPhoto2CameraEvent);
1160
1387
 
1161
1388
  // RESULT_CHECK_EVENT(gp_filesystem_reset(c->camera->fs), ce);
data/ext/gphoto2camera.h CHANGED
@@ -42,7 +42,11 @@ void camera_mark(GPhoto2Camera *c);
42
42
  void camera_free(GPhoto2Camera *c);
43
43
  VALUE camera_allocate(VALUE klass);
44
44
 
45
+
46
+
47
+
45
48
  VALUE camera_initialize(int argc, VALUE *argv, VALUE self);
49
+ VALUE camera_dispose(VALUE self);
46
50
  VALUE camera_class_ports(VALUE klass);
47
51
 
48
52
  VALUE camera_capture(int argc, VALUE *argv, VALUE self);
@@ -66,4 +70,9 @@ VALUE camera_create_folder(VALUE self, VALUE folder);
66
70
 
67
71
  VALUE camera_wait(int argc, VALUE *argv, VALUE self);
68
72
 
73
+ VALUE camera_model_name(VALUE self);
74
+ VALUE camera_has_image_capture(VALUE self);
75
+ VALUE camera_has_preview(VALUE self);
76
+ VALUE camera_has_config(VALUE self);
77
+
69
78
  #endif /* _INC_CAMERA */
@@ -35,6 +35,13 @@ int gp_result_check(int retval) {
35
35
  return retval;
36
36
  }
37
37
 
38
+ void check_disposed(GPhoto2Camera* c) {
39
+ if ((*c).disposed) {
40
+ rb_raise(rb_cGPhoto2Exception, "Camera has been disposed");
41
+ }
42
+ }
43
+
44
+
38
45
  VALUE getRadio(CameraWidget *cc) {
39
46
  const char *val;
40
47
 
@@ -272,3 +279,5 @@ void populateWithConfigs(CameraWidget *cc, VALUE hash) {
272
279
  }
273
280
  }
274
281
 
282
+
283
+
@@ -48,12 +48,16 @@ typedef struct {
48
48
 
49
49
  char *virtFolder;
50
50
  char *lastName;
51
+
52
+ CameraAbilities abilities;
53
+ int disposed;
51
54
  } GPhoto2Camera;
52
55
 
53
56
  extern VALUE rb_cGPhoto2Exception;
54
57
 
55
58
  void rb_raise_gp_result(int retval);
56
59
  int gp_result_check(int retval);
60
+ void check_disposed(GPhoto2Camera* c);
57
61
 
58
62
  VALUE getRadio(CameraWidget *cc);
59
63
  VALUE listRadio(CameraWidget *cc);
data/ext/gphoto4ruby.c CHANGED
@@ -85,6 +85,7 @@ void Init_gphoto4ruby() {
85
85
  rb_define_alloc_func(rb_cGPhoto2Camera, camera_allocate);
86
86
  rb_define_module_function(rb_cGPhoto2Camera, "ports", camera_class_ports, 0); /* in gphoto2camera.c */
87
87
  rb_define_method(rb_cGPhoto2Camera, "initialize", camera_initialize, -1); /* in gphoto2camera.c */
88
+ rb_define_method(rb_cGPhoto2Camera, "dispose", camera_dispose, 0); /* in gphoto2camera.c */
88
89
  rb_define_method(rb_cGPhoto2Camera, "config", camera_get_config, -1); /* in gphoto2camera.c */
89
90
  rb_define_method(rb_cGPhoto2Camera, "config_merge", camera_config_merge, 1); /* in gphoto2camera.c */
90
91
  rb_define_method(rb_cGPhoto2Camera, "[]", camera_get_value, -1); /* in gphoto2camera.c */
@@ -103,5 +104,10 @@ void Init_gphoto4ruby() {
103
104
 
104
105
  rb_define_method(rb_cGPhoto2CameraEvent, "type", camera_event_type, 0); /* in gphoto2camera_event.c */
105
106
  rb_define_method(rb_cGPhoto2CameraEvent, "file", camera_event_file, 0); /* in gphoto2camera_event.c */
107
+
108
+ rb_define_method(rb_cGPhoto2Camera, "model_name", camera_model_name, 0); /* in gphoto2camera.c */
109
+ rb_define_method(rb_cGPhoto2Camera, "has_image_capture?", camera_has_image_capture, 0); /* in gphoto2camera.c */
110
+ rb_define_method(rb_cGPhoto2Camera, "has_preview?", camera_has_preview, 0); /* in gphoto2camera.c */
111
+ rb_define_method(rb_cGPhoto2Camera, "has_config?", camera_has_config, 0); /* in gphoto2camera.c */
106
112
  }
107
113
 
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gphoto4ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 4
8
+ - 2
9
+ version: 0.4.2
5
10
  platform: ruby
6
11
  authors:
7
12
  - neq4 company
@@ -10,7 +15,7 @@ autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
17
 
13
- date: 2009-11-06 00:00:00 +03:00
18
+ date: 2010-02-28 00:00:00 +03:00
14
19
  default_executable:
15
20
  dependencies: []
16
21
 
@@ -65,18 +70,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
70
  requirements:
66
71
  - - ">="
67
72
  - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
68
75
  version: "0"
69
- version:
70
76
  required_rubygems_version: !ruby/object:Gem::Requirement
71
77
  requirements:
72
78
  - - ">="
73
79
  - !ruby/object:Gem::Version
80
+ segments:
81
+ - 0
74
82
  version: "0"
75
- version:
76
83
  requirements: []
77
84
 
78
85
  rubyforge_project: gphoto4ruby
79
- rubygems_version: 1.3.5
86
+ rubygems_version: 1.3.6
80
87
  signing_key:
81
88
  specification_version: 3
82
89
  summary: GPhoto4Ruby is Ruby wrapping around gphoto2 C library