ffi-gphoto2 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|