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 +4 -4
- data/README.md +4 -0
- data/examples/list_config.rb +37 -0
- data/examples/record_movie.rb +2 -4
- data/lib/gphoto2/camera.rb +19 -18
- data/lib/gphoto2/camera_widgets/camera_widget.rb +1 -1
- data/lib/gphoto2/camera_widgets/text_camera_widget.rb +6 -0
- data/lib/gphoto2/camera_widgets/toggle_camera_widget.rb +1 -0
- data/lib/gphoto2/version.rb +1 -1
- data/spec/gphoto2/camera_spec.rb +84 -24
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f540e98f060027da7173c2025502331090f5a24c
|
4
|
+
data.tar.gz: 27555b84f07e26724da18c72500e6c7483ec6916
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/examples/record_movie.rb
CHANGED
@@ -18,10 +18,8 @@ begin
|
|
18
18
|
# stop recording
|
19
19
|
camera.update(movie: false)
|
20
20
|
|
21
|
-
#
|
22
|
-
|
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
|
data/lib/gphoto2/camera.rb
CHANGED
@@ -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(
|
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(
|
30
|
-
camera = new(
|
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(
|
44
|
-
|
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(
|
48
|
-
@
|
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
|
80
|
-
|
81
|
-
|
82
|
-
|
81
|
+
def wait_for(event_type)
|
82
|
+
begin
|
83
|
+
event = wait
|
84
|
+
end until event.type == event_type
|
83
85
|
|
84
|
-
|
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
|
data/lib/gphoto2/version.rb
CHANGED
data/spec/gphoto2/camera_spec.rb
CHANGED
@@ -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
|
-
|
68
|
-
cameras =
|
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
|
-
|
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) {
|
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.
|
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-
|
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.
|
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
|