ffi-gphoto2 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b41989c0a0a69883e01f7f220c8afc02a7f14a6
4
- data.tar.gz: 437b613df85ec51ef13c28b160e0614bd84019ff
3
+ metadata.gz: f540e98f060027da7173c2025502331090f5a24c
4
+ data.tar.gz: 27555b84f07e26724da18c72500e6c7483ec6916
5
5
  SHA512:
6
- metadata.gz: 7b0ad2ed9e8ca01acbbee01466196f787e12c2472eefbe5dc51b56ae8abafa1598546310a7dca52eb464d681f688790c8650b950d1459ce40157fc0233430e48
7
- data.tar.gz: 9030436814f22ad5d8af8065cb8918c8f7503968afa44d745dd81720a2e4a38097ea21af371b42aa5c75289931cd13704fde8a83136211dd9a0504b57bf62f19
6
+ metadata.gz: f7fc0ad08a779b3de0b29a54b2624b367a350b4203b7ab174e1089955fd171a67645943227954fd78730a95eb4754a572bed4a788a35aba51bf654b567aff31f
7
+ data.tar.gz: 355b62d70d3c67322631093a1c4d32ee84bdcfbd5bd2b5ba1eafda2171e99d9e38245c799b1daed6c1e59795d0514f0d6406098c58f9cd7dd92aa3163a013e0a
data/README.md CHANGED
@@ -36,6 +36,10 @@ canonical Ruby way.
36
36
  # ...or even search by model name
37
37
  camera = GPhoto2::Camera.where(/nikon/i).first
38
38
 
39
+ # check camera abilities
40
+ camera.can? :capture_image
41
+ # => true
42
+
39
43
  # list camera configuration names
40
44
  camera.config.keys
41
45
  # => ['autofocusdrive', 'manualfocusdrive', 'controlmode', ...]
@@ -0,0 +1,37 @@
1
+ require 'gphoto2'
2
+
3
+ def visit(widget, level = 0)
4
+ indent = ' ' * level
5
+
6
+ puts "#{indent}#{widget.name}"
7
+
8
+ if widget.type == :window || widget.type == :section
9
+ widget.children.each { |child| visit(child, level + 1) }
10
+ return
11
+ end
12
+
13
+ indent << ' '
14
+
15
+ puts "#{indent}type: #{widget.type}"
16
+
17
+ return if widget.type == :menu
18
+
19
+ puts "#{indent}value: #{widget.value}"
20
+
21
+ case widget.type
22
+ when :range
23
+ range = widget.range
24
+ step = (range.size > 1) ? range[1] - range[0] : 1.0
25
+ puts "#{indent}options: #{range.first}..#{range.last}:step(#{step})"
26
+ when :radio
27
+ puts "#{indent}options: #{widget.choices.inspect}"
28
+ end
29
+ end
30
+
31
+ camera = GPhoto2::Camera.first
32
+
33
+ begin
34
+ visit(camera.window)
35
+ ensure
36
+ camera.finalize
37
+ end
@@ -18,10 +18,8 @@ begin
18
18
  # stop recording
19
19
  camera.update(movie: false)
20
20
 
21
- # wait for the camera to finish with the file
22
- begin
23
- event = camera.wait
24
- end until event.type == :file_added
21
+ # block until the camera finishes with the file
22
+ event = camera.wait_for(:file_added)
25
23
 
26
24
  # the event data has a camera file that can be saved
27
25
  event.data.save
@@ -2,7 +2,7 @@ module GPhoto2
2
2
  class Camera
3
3
  include FFI::GPhoto2
4
4
 
5
- attr_reader :context, :port
5
+ attr_reader :context, :model, :port
6
6
 
7
7
  def self.all
8
8
  context = Context.new
@@ -12,7 +12,7 @@ module GPhoto2
12
12
 
13
13
  entries = cameras.to_a.map do |entry|
14
14
  model, port = entry.name, entry.value
15
- Camera.new(port, model)
15
+ Camera.new(model, port)
16
16
  end
17
17
 
18
18
  context.finalize
@@ -26,8 +26,8 @@ module GPhoto2
26
26
  entries.first
27
27
  end
28
28
 
29
- def self.open(port, model = nil)
30
- camera = new(port, model)
29
+ def self.open(model, port)
30
+ camera = new(model, port)
31
31
 
32
32
  if block_given?
33
33
  begin
@@ -40,12 +40,14 @@ module GPhoto2
40
40
  end
41
41
  end
42
42
 
43
- def self.where(pattern)
44
- all.select { |c| c.model.match(pattern) }
43
+ def self.where(condition)
44
+ name = condition.keys.first
45
+ pattern = condition.values.first
46
+ all.select { |c| c.send(name).match(pattern) }
45
47
  end
46
48
 
47
- def initialize(port, model = nil)
48
- @port, @model = port, model
49
+ def initialize(model, port)
50
+ @model, @port = model, port
49
51
  @dirty = false
50
52
  end
51
53
 
@@ -76,17 +78,12 @@ module GPhoto2
76
78
  wait_for_event(timeout)
77
79
  end
78
80
 
79
- def model
80
- @model ||= begin
81
- abilities = CameraAbilitiesList.new(context).detect
82
- cameras = abilities.detect
81
+ def wait_for(event_type)
82
+ begin
83
+ event = wait
84
+ end until event.type == event_type
83
85
 
84
- entry = cameras.map(&:value).find { |port| port == @port }
85
-
86
- raise RuntimeError, "no camera found on port #{@port}" if entry.nil?
87
-
88
- entry.name
89
- end
86
+ event
90
87
  end
91
88
 
92
89
  def ptr
@@ -149,6 +146,10 @@ module GPhoto2
149
146
  @dirty
150
147
  end
151
148
 
149
+ def can?(operation)
150
+ (abilities[:operations] & CameraOperation[operation]) != 0
151
+ end
152
+
152
153
  def save
153
154
  return false unless dirty?
154
155
  set_config
@@ -41,7 +41,7 @@ module GPhoto2
41
41
  def children
42
42
  count_children.times.map { |i| get_child(i) }
43
43
  end
44
-
44
+
45
45
  def flatten(map = {})
46
46
  case type
47
47
  when :window, :section
@@ -10,5 +10,11 @@ module GPhoto2
10
10
  GPhoto2.check!(rc)
11
11
  val_ptr.read_pointer.read_string
12
12
  end
13
+
14
+ def set_value(text)
15
+ val = FFI::MemoryPointer.from_string(text)
16
+ rc = gp_widget_set_value(ptr, val)
17
+ GPhoto2.check!(rc)
18
+ end
13
19
  end
14
20
  end
@@ -5,6 +5,7 @@ module GPhoto2
5
5
  def get_value
6
6
  val = FFI::MemoryPointer.new(:int)
7
7
  rc = gp_widget_get_value(ptr, val)
8
+ GPhoto2.check!(rc)
8
9
  (val.read_int == 1)
9
10
  end
10
11
 
@@ -1,3 +1,3 @@
1
1
  module GPhoto2
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -2,12 +2,13 @@ require 'spec_helper'
2
2
 
3
3
  module GPhoto2
4
4
  describe Camera do
5
+ let(:model) { 'Nikon DSC D5100 (PTP mode)' }
5
6
  let(:port) { 'usb:250,006' }
6
7
 
7
8
  describe '.all' do
8
9
  let(:abilities_list) { double('camera_abilities_list') }
9
10
  let(:camera_list) { double('camera_list') }
10
- let(:camera) { Camera.new(port) }
11
+ let(:camera) { Camera.new(model, port) }
11
12
 
12
13
  before do
13
14
  Context.stub(:stub)
@@ -26,7 +27,7 @@ module GPhoto2
26
27
  describe '.first' do
27
28
  context 'when devices are automatically detected' do
28
29
  it 'returns a new Camera using the first entry' do
29
- camera = Camera.new(port)
30
+ camera = Camera.new(model, port)
30
31
  Camera.stub(:all).and_return([camera])
31
32
  expect(Camera.first).to be_kind_of(Camera)
32
33
  end
@@ -47,33 +48,51 @@ module GPhoto2
47
48
  context 'when a block is given' do
48
49
  it 'yeilds a new camera instance' do
49
50
  expect(Camera).to receive(:open).and_yield(camera)
50
- Camera.open(port) { |c| }
51
+ Camera.open(model, port) { |c| }
51
52
  end
52
53
 
53
54
  it 'finalizes the camera when the block terminates' do
54
55
  expect(camera).to receive(:finalize)
55
- Camera.open(port) { |c| }
56
+ Camera.open(model, port) { |c| }
56
57
  end
57
58
  end
58
59
 
59
60
  context 'when no block is given' do
60
61
  it 'returns a new camera instance' do
61
- expect(Camera.open(port)).to eq(camera)
62
+ expect(Camera.open(model, port)).to eq(camera)
62
63
  end
63
64
  end
64
65
  end
65
66
 
66
67
  describe '.where' do
67
- it 'filters all detected cameras by model' do
68
- cameras = %w[cheese toast wine].map { |model| double('camera', model: model) }
68
+ let(:cameras) do
69
+ cameras = []
70
+ cameras << double('camera', model: 'Canon EOS 5D Mark III', port: 'usb:250,004')
71
+ cameras << double('camera', model: 'Nikon DSC D800', port: 'usb:250,005')
72
+ cameras << double('camera', model: 'Nikon DSC D5100', port: 'usb:250,006')
73
+ cameras
74
+ end
75
+
76
+ before do
69
77
  Camera.stub(:all).and_return(cameras)
70
- expect(Camera.where(/e/)).to match_array([cameras[0], cameras[2]])
78
+ end
79
+
80
+ it 'filters all detected cameras by model' do
81
+ actual = Camera.where(model: /nikon/i)
82
+ expected = [cameras[1], cameras[2]]
83
+ expect(actual).to match_array(expected)
84
+ end
85
+
86
+ it 'filters all detected cameras by port' do
87
+ actual = Camera.where(port: 'usb:250,004')
88
+ expected = [cameras[0]]
89
+ expect(actual).to match_array(expected)
71
90
  end
72
91
  end
73
92
 
74
93
  describe '#exit' do
75
94
  it 'closes the camera connection' do
76
- camera = Camera.new(port)
95
+ camera = Camera.new(model, port)
77
96
  camera.stub(:_exit)
78
97
  expect(camera).to receive(:_exit)
79
98
  camera.exit
@@ -81,7 +100,7 @@ module GPhoto2
81
100
  end
82
101
 
83
102
  describe '#capture' do
84
- let(:camera) { Camera.new(port) }
103
+ let(:camera) { Camera.new(model, port) }
85
104
  let(:path) { double('camera_file_path', folder: 'folder', name: 'name') }
86
105
 
87
106
  before do
@@ -100,7 +119,7 @@ module GPhoto2
100
119
  end
101
120
 
102
121
  describe '#preview' do
103
- let(:camera) { Camera.new(port) }
122
+ let(:camera) { Camera.new(model, port) }
104
123
  let(:file) { double('camera_file') }
105
124
 
106
125
  before do
@@ -119,8 +138,8 @@ module GPhoto2
119
138
  end
120
139
 
121
140
  describe '#wait' do
122
- let(:camera) { Camera.new(port) }
123
- let(:event) { :capture_complete }
141
+ let(:camera) { Camera.new(model, port) }
142
+ let(:event) { double('camera_event') }
124
143
 
125
144
  before do
126
145
  camera.stub(:wait_for_event).and_return(event)
@@ -136,8 +155,26 @@ module GPhoto2
136
155
  end
137
156
  end
138
157
 
158
+ describe '#wait_for' do
159
+ let(:camera) { Camera.new(model, port) }
160
+ let(:event) { double('camera_event', type: :capture_complete) }
161
+
162
+ before do
163
+ camera.stub(:wait).and_return(event)
164
+ end
165
+
166
+ it 'blocks until a given event is returned from #wait' do
167
+ expect(camera).to receive(:wait)
168
+ camera.wait_for(:capture_complete)
169
+ end
170
+
171
+ it 'returns the first event of the given type' do
172
+ expect(camera.wait_for(:capture_complete)).to eq(event)
173
+ end
174
+ end
175
+
139
176
  describe '#window' do
140
- let(:camera) { Camera.new(port) }
177
+ let(:camera) { Camera.new(model, port) }
141
178
  let(:window) { double('camera_widget') }
142
179
 
143
180
  it 'always returns the same CameraWidget instance' do
@@ -149,7 +186,7 @@ module GPhoto2
149
186
 
150
187
  describe '#config' do
151
188
  it 'returns a map of configuration widgets' do
152
- camera = Camera.new(port)
189
+ camera = Camera.new(model, port)
153
190
  window = double('camera_widget')
154
191
  camera.stub(:window).and_return(window)
155
192
  window.stub(:flatten).and_return({ 'iso' => window })
@@ -159,7 +196,7 @@ module GPhoto2
159
196
  end
160
197
 
161
198
  describe '#filesystem' do
162
- let(:camera) { Camera.new(port) }
199
+ let(:camera) { Camera.new(model, port) }
163
200
 
164
201
  context 'when a path is passed' do
165
202
  let(:path) { '/store_00010001' }
@@ -185,7 +222,7 @@ module GPhoto2
185
222
 
186
223
  describe '#file' do
187
224
  it 'retrieves a file from the camera' do
188
- camera = Camera.new(port)
225
+ camera = Camera.new(model, port)
189
226
  camera.stub(:file_get)
190
227
  expect(camera).to receive(:file_get)
191
228
  camera.file(double('camera_file'))
@@ -194,7 +231,7 @@ module GPhoto2
194
231
 
195
232
  describe '#delete' do
196
233
  it 'deletes a file from the camera' do
197
- camera = Camera.new(port)
234
+ camera = Camera.new(model, port)
198
235
  camera.stub(:file_delete)
199
236
  expect(camera).to receive(:file_delete)
200
237
  camera.delete(double('camera_file'))
@@ -205,7 +242,7 @@ module GPhoto2
205
242
  let(:window) { double('camera_widget') }
206
243
 
207
244
  let(:camera) do
208
- camera = Camera.new(port)
245
+ camera = Camera.new(model, port)
209
246
  camera.stub(:config).and_return({ 'iso' => window })
210
247
  camera
211
248
  end
@@ -231,7 +268,7 @@ module GPhoto2
231
268
  end
232
269
 
233
270
  let(:camera) do
234
- camera = Camera.new(port)
271
+ camera = Camera.new(model, port)
235
272
  camera.stub(:[]).and_return(window)
236
273
  camera
237
274
  end
@@ -252,7 +289,7 @@ module GPhoto2
252
289
 
253
290
  describe '#update' do
254
291
  let(:camera) do
255
- camera = Camera.new(port)
292
+ camera = Camera.new(model, port)
256
293
  camera.stub(:[]=)
257
294
  camera.stub(:save)
258
295
  camera
@@ -272,7 +309,7 @@ module GPhoto2
272
309
  describe '#dirty?' do
273
310
  context 'when the configuration changed' do
274
311
  it 'returns true' do
275
- camera = Camera.new(port)
312
+ camera = Camera.new(model, port)
276
313
  camera.stub_chain(:[], :value=)
277
314
 
278
315
  camera['iso'] = 400
@@ -283,15 +320,38 @@ module GPhoto2
283
320
 
284
321
  context 'when the configuration has not changed' do
285
322
  it 'returns false' do
286
- camera = Camera.new(port)
323
+ camera = Camera.new(model, port)
287
324
  expect(camera).not_to be_dirty
288
325
  end
289
326
  end
290
327
  end
291
328
 
329
+ describe '#can?' do
330
+ let(:camera) { Camera.new(model, port) }
331
+ let(:operations) { FFI::GPhoto2::CameraOperation[:capture_image] }
332
+
333
+ before do
334
+ camera.stub_chain(:abilities, :[])
335
+ .with(:operations)
336
+ .and_return(operations)
337
+ end
338
+
339
+ context 'when the camera does not have the ability perform an operation' do
340
+ it 'return false' do
341
+ expect(camera.can?(:capture_audio)).to be_false
342
+ end
343
+ end
344
+
345
+ context 'when the camera does have the ability to perform an operation' do
346
+ it 'returns true' do
347
+ expect(camera.can?(:capture_image)).to be_true
348
+ end
349
+ end
350
+ end
351
+
292
352
  describe '#save' do
293
353
  let(:camera) do
294
- camera = Camera.new(port)
354
+ camera = Camera.new(model, port)
295
355
  camera.stub_chain(:[], :value=)
296
356
  camera.stub(:set_config)
297
357
  camera
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffi-gphoto2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Macias
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-09-05 00:00:00.000000000 Z
11
+ date: 2013-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,7 @@ files:
80
80
  - README.md
81
81
  - Rakefile
82
82
  - examples/intervalometer.rb
83
+ - examples/list_config.rb
83
84
  - examples/live_view.rb
84
85
  - examples/record_movie.rb
85
86
  - ffi-gphoto2.gemspec
@@ -171,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
172
  requirements:
172
173
  - libgphoto2 >= 2.5.0
173
174
  rubyforge_project:
174
- rubygems_version: 2.0.3
175
+ rubygems_version: 2.0.7
175
176
  signing_key:
176
177
  specification_version: 4
177
178
  summary: A Ruby FFI for common functions in libgphoto2