alsa-backup 0.0.8 → 0.10
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/COPYING +674 -0
- data/COPYRIGHT +14 -0
- data/Manifest.txt +5 -3
- data/README.rdoc +12 -22
- data/Rakefile +65 -65
- data/alsa-backup.gemspec +14 -14
- data/lib/alsa_backup.rb +1 -1
- data/lib/alsa_backup/core_ext.rb +14 -0
- data/lib/alsa_backup/recorder.rb +9 -2
- data/lib/alsa_backup/writer.rb +4 -3
- data/lib/syslog_logger.rb +190 -0
- data/setup.rb +1585 -0
- data/spec/alsa_backup/cli_spec.rb +1 -1
- data/spec/alsa_backup/length_recorder_spec.rb +41 -0
- data/spec/alsa_backup/recorder_spec.rb +30 -0
- data/spec/alsa_backup/writer_spec.rb +83 -13
- data/spec/spec_helper.rb +2 -0
- data/tasks/rspec.rake +0 -6
- metadata +74 -31
- data/lib/alsa.rb +0 -299
- data/spec/alsa/pcm_spec.rb +0 -7
- data/spec/alsa_backup_spec.rb +0 -11
@@ -16,7 +16,7 @@ describe AlsaBackup::CLI, "execute" do
|
|
16
16
|
options = { :file => @file, :length => 2 }.update(options)
|
17
17
|
arguments = options.collect do |key,value|
|
18
18
|
if value
|
19
|
-
|
19
|
+
"--#{key}".tap do |argument|
|
20
20
|
argument << "=#{value}" unless value == true
|
21
21
|
end
|
22
22
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe AlsaBackup::LengthController do
|
4
|
+
|
5
|
+
def continue_after(frame_count)
|
6
|
+
simple_matcher("continue after #{frame_count} frames") do |actual|
|
7
|
+
actual.continue_after?(frame_count)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe AlsaBackup::LengthController::Loop do
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
@controller = AlsaBackup::LengthController::Loop.new
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should always continue" do
|
18
|
+
@controller.should continue_after(123)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe AlsaBackup::LengthController::FrameCount do
|
24
|
+
|
25
|
+
before(:each) do
|
26
|
+
@controller = AlsaBackup::LengthController::FrameCount.new(123)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should not continue after controller frame count" do
|
30
|
+
@controller.should_not continue_after(@controller.frame_count)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should decrement controller frame count after each test" do
|
34
|
+
lambda {
|
35
|
+
@controller.continue_after?(10)
|
36
|
+
}.should change(@controller, :frame_count).by(-10)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -47,6 +47,20 @@ describe AlsaBackup::Recorder do
|
|
47
47
|
@recorder.start
|
48
48
|
end
|
49
49
|
|
50
|
+
describe "alsa_options" do
|
51
|
+
|
52
|
+
it "should use buffer_time if specified" do
|
53
|
+
@recorder.buffer_time = 100000
|
54
|
+
@recorder.alsa_options[:buffer_time].should == 100000
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should use period_time if specified" do
|
58
|
+
@recorder.period_time = 100000
|
59
|
+
@recorder.alsa_options[:period_time].should == 100000
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
50
64
|
describe "error handler" do
|
51
65
|
|
52
66
|
class TestErrorHandler
|
@@ -142,4 +156,20 @@ describe AlsaBackup::Recorder do
|
|
142
156
|
|
143
157
|
end
|
144
158
|
|
159
|
+
describe "open_capture" do
|
160
|
+
|
161
|
+
it "should use specified device" do
|
162
|
+
@recorder.stub :device => "dummy"
|
163
|
+
ALSA::PCM::Capture.should_receive(:open).with("dummy", anything())
|
164
|
+
@recorder.open_capture {}
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should use alsa_options" do
|
168
|
+
@recorder.stub :alsa_options => { :dummy => true }
|
169
|
+
ALSA::PCM::Capture.should_receive(:open).with(anything(), @recorder.alsa_options)
|
170
|
+
@recorder.open_capture {}
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
145
175
|
end
|
@@ -8,7 +8,7 @@ describe AlsaBackup::Writer do
|
|
8
8
|
@writer = AlsaBackup::Writer.new :directory => @directory, :file => @file
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
context "when created" do
|
12
12
|
|
13
13
|
it "should use the :directory option as directory" do
|
14
14
|
AlsaBackup::Writer.new(:directory => @directory).directory.should == @directory
|
@@ -34,33 +34,103 @@ describe AlsaBackup::Writer do
|
|
34
34
|
|
35
35
|
end
|
36
36
|
|
37
|
-
describe "on_close" do
|
37
|
+
describe "#on_close" do
|
38
|
+
|
39
|
+
class TestCallback
|
40
|
+
|
41
|
+
attr_reader :file
|
42
|
+
|
43
|
+
def call(file)
|
44
|
+
@file = file
|
45
|
+
end
|
46
|
+
|
47
|
+
def invoked?
|
48
|
+
not @file.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:callback) { TestCallback.new }
|
54
|
+
|
55
|
+
before(:each) do
|
56
|
+
@writer.on_close_callbacks << callback
|
57
|
+
end
|
38
58
|
|
39
|
-
it "should
|
40
|
-
AlsaBackup::Writer.should_receive(:delete_empty_file).with(@file)
|
59
|
+
it "should check if file is empty" do
|
60
|
+
AlsaBackup::Writer.should_receive(:delete_empty_file).with(@file).and_return(true)
|
41
61
|
@writer.on_close(@file)
|
42
62
|
end
|
43
63
|
|
44
|
-
|
45
|
-
file_given_to_proc = nil
|
64
|
+
context "when file was empty" do
|
46
65
|
|
47
|
-
|
48
|
-
|
66
|
+
before(:each) do
|
67
|
+
AlsaBackup::Writer.stub :delete_empty_file => true
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not invoke callbacks" do
|
71
|
+
@writer.on_close(@file)
|
72
|
+
callback.should_not be_invoked
|
49
73
|
end
|
50
|
-
@writer.on_close(@file)
|
51
74
|
|
52
|
-
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should invoke all on_close_callbacks" do
|
78
|
+
@writer.on_close(@file)
|
79
|
+
callback.should be_invoked
|
53
80
|
end
|
54
81
|
|
55
82
|
it "should ignore exception from callbacks" do
|
56
|
-
|
57
|
-
raise "Error"
|
58
|
-
end
|
83
|
+
callback.stub!(:call).and_raise("Error")
|
59
84
|
lambda { @writer.on_close(@file) }.should_not raise_error
|
60
85
|
end
|
61
86
|
|
62
87
|
end
|
63
88
|
|
89
|
+
describe ".delete_empty_file" do
|
90
|
+
|
91
|
+
let(:file) { "tmp/deleted_empty_file" }
|
92
|
+
|
93
|
+
after(:each) do
|
94
|
+
File.delete(file) if File.exists?(file)
|
95
|
+
end
|
96
|
+
|
97
|
+
context "when file contains 44 bytes or less" do
|
98
|
+
|
99
|
+
before(:each) do
|
100
|
+
File.open(file, "w") { |f| f.write 'a'*44 }
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should remove a file" do
|
104
|
+
AlsaBackup::Writer.delete_empty_file(file)
|
105
|
+
File.exists?(file).should be_false
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should return true" do
|
109
|
+
AlsaBackup::Writer.delete_empty_file(file).should be_true
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
context "when file contains more than 44 bytes" do
|
115
|
+
|
116
|
+
before(:each) do
|
117
|
+
File.open(file, "w") { |f| f.write "a"*45 }
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should not remove the file" do
|
121
|
+
AlsaBackup::Writer.delete_empty_file(file)
|
122
|
+
File.exists?(file).should be_true
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return false" do
|
126
|
+
AlsaBackup::Writer.delete_empty_file(file).should be_false
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
end
|
133
|
+
|
64
134
|
describe "file" do
|
65
135
|
|
66
136
|
it "should accept file as string" do
|
data/spec/spec_helper.rb
CHANGED
data/tasks/rspec.rake
CHANGED
@@ -14,12 +14,6 @@ EOS
|
|
14
14
|
exit(0)
|
15
15
|
end
|
16
16
|
|
17
|
-
desc "Run the specs under spec/models"
|
18
|
-
Spec::Rake::SpecTask.new do |t|
|
19
|
-
t.spec_opts = ['--options', "spec/spec.opts"]
|
20
|
-
t.spec_files = FileList['spec/**/*_spec.rb']
|
21
|
-
end
|
22
|
-
|
23
17
|
namespace :spec do
|
24
18
|
desc "Generate spec HTML report"
|
25
19
|
Spec::Rake::SpecTask.new('html') do |t|
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alsa-backup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 31
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 10
|
9
|
+
version: "0.10"
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Alban Peignier
|
@@ -9,59 +14,89 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-10-14 00:00:00 +02:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: ffi
|
17
|
-
|
18
|
-
|
19
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
20
25
|
requirements:
|
21
26
|
- - ">="
|
22
27
|
- !ruby/object:Gem::Version
|
28
|
+
hash: 25
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
- 3
|
32
|
+
- 5
|
23
33
|
version: 0.3.5
|
24
|
-
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
25
36
|
- !ruby/object:Gem::Dependency
|
26
37
|
name: newgem
|
27
|
-
|
28
|
-
|
29
|
-
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
30
41
|
requirements:
|
31
42
|
- - ">="
|
32
43
|
- !ruby/object:Gem::Version
|
33
|
-
|
34
|
-
|
44
|
+
hash: 5
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 5
|
48
|
+
- 3
|
49
|
+
version: 1.5.3
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
35
52
|
- !ruby/object:Gem::Dependency
|
36
53
|
name: daemons
|
37
|
-
|
38
|
-
|
39
|
-
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
40
57
|
requirements:
|
41
58
|
- - ">="
|
42
59
|
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 1
|
63
|
+
- 0
|
64
|
+
- 10
|
43
65
|
version: 1.0.10
|
44
|
-
|
66
|
+
type: :runtime
|
67
|
+
version_requirements: *id003
|
45
68
|
- !ruby/object:Gem::Dependency
|
46
69
|
name: newgem
|
47
|
-
|
48
|
-
|
49
|
-
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
50
73
|
requirements:
|
51
74
|
- - ">="
|
52
75
|
- !ruby/object:Gem::Version
|
53
|
-
|
54
|
-
|
76
|
+
hash: 5
|
77
|
+
segments:
|
78
|
+
- 1
|
79
|
+
- 5
|
80
|
+
- 3
|
81
|
+
version: 1.5.3
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id004
|
55
84
|
- !ruby/object:Gem::Dependency
|
56
85
|
name: hoe
|
57
|
-
|
58
|
-
|
59
|
-
|
86
|
+
prerelease: false
|
87
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
88
|
+
none: false
|
60
89
|
requirements:
|
61
90
|
- - ">="
|
62
91
|
- !ruby/object:Gem::Version
|
63
|
-
|
64
|
-
|
92
|
+
hash: 19
|
93
|
+
segments:
|
94
|
+
- 2
|
95
|
+
- 6
|
96
|
+
- 2
|
97
|
+
version: 2.6.2
|
98
|
+
type: :development
|
99
|
+
version_requirements: *id005
|
65
100
|
description: ALSA client to perform continuous recording
|
66
101
|
email:
|
67
102
|
- alban@tryphon.eu
|
@@ -75,6 +110,8 @@ extra_rdoc_files:
|
|
75
110
|
- PostInstall.txt
|
76
111
|
files:
|
77
112
|
- .autotest
|
113
|
+
- COPYING
|
114
|
+
- COPYRIGHT
|
78
115
|
- History.txt
|
79
116
|
- Manifest.txt
|
80
117
|
- PostInstall.txt
|
@@ -84,7 +121,6 @@ files:
|
|
84
121
|
- alsa-backup.gemspec
|
85
122
|
- bin/alsa-backup
|
86
123
|
- config.sample
|
87
|
-
- lib/alsa.rb
|
88
124
|
- lib/alsa_backup.rb
|
89
125
|
- lib/alsa_backup/cli.rb
|
90
126
|
- lib/alsa_backup/core_ext.rb
|
@@ -92,15 +128,16 @@ files:
|
|
92
128
|
- lib/alsa_backup/recorder.rb
|
93
129
|
- lib/alsa_backup/writer.rb
|
94
130
|
- lib/sndfile.rb
|
131
|
+
- lib/syslog_logger.rb
|
95
132
|
- script/console
|
96
133
|
- script/destroy
|
97
134
|
- script/generate
|
98
|
-
-
|
135
|
+
- setup.rb
|
99
136
|
- spec/alsa_backup/cli_spec.rb
|
100
137
|
- spec/alsa_backup/core_ext_spec.rb
|
138
|
+
- spec/alsa_backup/length_recorder_spec.rb
|
101
139
|
- spec/alsa_backup/recorder_spec.rb
|
102
140
|
- spec/alsa_backup/writer_spec.rb
|
103
|
-
- spec/alsa_backup_spec.rb
|
104
141
|
- spec/fixtures/config_test.rb
|
105
142
|
- spec/sndfile/info_spec.rb
|
106
143
|
- spec/spec.opts
|
@@ -117,21 +154,27 @@ rdoc_options:
|
|
117
154
|
require_paths:
|
118
155
|
- lib
|
119
156
|
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
none: false
|
120
158
|
requirements:
|
121
159
|
- - ">="
|
122
160
|
- !ruby/object:Gem::Version
|
161
|
+
hash: 3
|
162
|
+
segments:
|
163
|
+
- 0
|
123
164
|
version: "0"
|
124
|
-
version:
|
125
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
none: false
|
126
167
|
requirements:
|
127
168
|
- - ">="
|
128
169
|
- !ruby/object:Gem::Version
|
170
|
+
hash: 3
|
171
|
+
segments:
|
172
|
+
- 0
|
129
173
|
version: "0"
|
130
|
-
version:
|
131
174
|
requirements: []
|
132
175
|
|
133
176
|
rubyforge_project: alsa-backup
|
134
|
-
rubygems_version: 1.3.
|
177
|
+
rubygems_version: 1.3.7
|
135
178
|
signing_key:
|
136
179
|
specification_version: 3
|
137
180
|
summary: ALSA client to perform continuous recording
|
data/lib/alsa.rb
DELETED
@@ -1,299 +0,0 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
|
3
|
-
require 'logger'
|
4
|
-
|
5
|
-
module ALSA
|
6
|
-
|
7
|
-
def self.logger
|
8
|
-
unless @logger
|
9
|
-
@logger = Logger.new(STDERR)
|
10
|
-
@logger.level = Logger::WARN
|
11
|
-
end
|
12
|
-
|
13
|
-
@logger
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.logger=(logger); @logger = logger; end
|
17
|
-
|
18
|
-
def self.try_to(message, &block)
|
19
|
-
logger.debug { message }
|
20
|
-
if ALSA::Native::error_code?(response = yield)
|
21
|
-
raise "cannot #{message} (#{ALSA::Native::strerror(response)})"
|
22
|
-
else
|
23
|
-
response
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
module Native
|
28
|
-
extend FFI::Library
|
29
|
-
ffi_lib "libasound.so"
|
30
|
-
|
31
|
-
attach_function :strerror, :snd_strerror, [:int], :string
|
32
|
-
|
33
|
-
def self.error_code?(response)
|
34
|
-
response < 0
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
module PCM
|
39
|
-
|
40
|
-
class Capture
|
41
|
-
|
42
|
-
attr_accessor :handle
|
43
|
-
|
44
|
-
def self.open(device, hardware_attributes = {}, &block)
|
45
|
-
Capture.new.open(device, hardware_attributes, &block)
|
46
|
-
end
|
47
|
-
|
48
|
-
def open(device, hardware_attributes = {}, &block)
|
49
|
-
capture_handle = FFI::MemoryPointer.new :pointer
|
50
|
-
ALSA::try_to "open audio device #{device}" do
|
51
|
-
ALSA::PCM::Native::open capture_handle, device, ALSA::PCM::Native::STREAM_CAPTURE, ALSA::PCM::Native::BLOCK
|
52
|
-
end
|
53
|
-
self.handle = capture_handle.read_pointer
|
54
|
-
|
55
|
-
self.hardware_parameters=hardware_attributes
|
56
|
-
|
57
|
-
if block_given?
|
58
|
-
begin
|
59
|
-
yield self
|
60
|
-
ensure
|
61
|
-
self.close
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def change_hardware_parameters
|
67
|
-
hw_params = HwParameters.new(self).default_for_device
|
68
|
-
|
69
|
-
begin
|
70
|
-
yield hw_params
|
71
|
-
|
72
|
-
ALSA::try_to "set hw parameters" do
|
73
|
-
ALSA::PCM::Native::hw_params self.handle, hw_params.handle
|
74
|
-
end
|
75
|
-
ensure
|
76
|
-
hw_params.free
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def hardware_parameters
|
81
|
-
HwParameters.new(self).current_for_device
|
82
|
-
end
|
83
|
-
alias_method :hw_params, :hardware_parameters
|
84
|
-
|
85
|
-
def hardware_parameters=(attributes= {})
|
86
|
-
attributes = {:access => :rw_interleaved}.update(attributes)
|
87
|
-
change_hardware_parameters do |hw_params|
|
88
|
-
hw_params.update_attributes(attributes)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def read
|
93
|
-
ALSA.logger.debug { "start read with #{hw_params.sample_rate}, #{hw_params.channels} channels"}
|
94
|
-
|
95
|
-
# use an 500ms buffer
|
96
|
-
frame_count = hw_params.sample_rate / 2
|
97
|
-
ALSA.logger.debug { "allocate #{hw_params.buffer_size_for(frame_count)} bytes for #{frame_count} frames" }
|
98
|
-
FFI::MemoryPointer.new(:char, hw_params.buffer_size_for(frame_count)) do |buffer|
|
99
|
-
begin
|
100
|
-
read_buffer buffer, frame_count
|
101
|
-
end while yield buffer, frame_count
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def read_buffer(buffer, frame_count)
|
106
|
-
read_count = ALSA::try_to "read from audio interface" do
|
107
|
-
response = ALSA::PCM::Native::readi(self.handle, buffer, frame_count)
|
108
|
-
if ALSA::Native::error_code?(response)
|
109
|
-
ALSA.logger.warn { "try to recover '#{ALSA::Native::strerror(response)}' on read"}
|
110
|
-
ALSA::PCM::Native::pcm_recover(self.handle, response, 1)
|
111
|
-
else
|
112
|
-
response
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
missing_frame_count = frame_count - read_count
|
117
|
-
if missing_frame_count > 0
|
118
|
-
ALSA.logger.debug { "re-read missing frame count: #{missing_frame_count}"}
|
119
|
-
read_buffer_size = hw_params.buffer_size_for(read_count)
|
120
|
-
# buffer[read_buffer_size] doesn't return a MemoryPointer
|
121
|
-
read_buffer(buffer + read_buffer_size, missing_frame_count)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def close
|
126
|
-
ALSA::try_to "close audio device" do
|
127
|
-
ALSA::PCM::Native::close self.handle
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
class HwParameters
|
132
|
-
|
133
|
-
attr_accessor :handle, :device
|
134
|
-
|
135
|
-
def initialize(device = nil)
|
136
|
-
hw_params_pointer = FFI::MemoryPointer.new :pointer
|
137
|
-
|
138
|
-
ALSA::PCM::Native::hw_params_malloc hw_params_pointer
|
139
|
-
self.handle = hw_params_pointer.read_pointer
|
140
|
-
|
141
|
-
self.device = device if device
|
142
|
-
end
|
143
|
-
|
144
|
-
def update_attributes(attributes)
|
145
|
-
attributes.each_pair { |name, value| send("#{name}=", value) }
|
146
|
-
end
|
147
|
-
|
148
|
-
def default_for_device
|
149
|
-
ALSA::try_to "initialize hardware parameter structure" do
|
150
|
-
ALSA::PCM::Native::hw_params_any device.handle, self.handle
|
151
|
-
end
|
152
|
-
self
|
153
|
-
end
|
154
|
-
|
155
|
-
def current_for_device
|
156
|
-
ALSA::try_to "retrieve current hardware parameters" do
|
157
|
-
ALSA::PCM::Native::hw_params_current device.handle, self.handle
|
158
|
-
end
|
159
|
-
self
|
160
|
-
end
|
161
|
-
|
162
|
-
def access=(access)
|
163
|
-
ALSA::try_to "set access type" do
|
164
|
-
ALSA::PCM::Native::hw_params_set_access self.device.handle, self.handle, ALSA::PCM::Native::Access.const_get(access.to_s.upcase)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def channels=(channels)
|
169
|
-
ALSA::try_to "set channel count : #{channels}" do
|
170
|
-
ALSA::PCM::Native::hw_params_set_channels self.device.handle, self.handle, channels
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
def sample_rate=(sample_rate)
|
175
|
-
ALSA::try_to "set sample rate" do
|
176
|
-
rate = FFI::MemoryPointer.new(:int)
|
177
|
-
rate.write_int(sample_rate)
|
178
|
-
|
179
|
-
dir = FFI::MemoryPointer.new(:int)
|
180
|
-
dir.write_int(0)
|
181
|
-
|
182
|
-
error_code = ALSA::PCM::Native::hw_params_set_rate_near self.device.handle, self.handle, rate, dir
|
183
|
-
|
184
|
-
rate.free
|
185
|
-
dir.free
|
186
|
-
|
187
|
-
error_code
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
def sample_rate
|
192
|
-
rate = nil
|
193
|
-
ALSA::try_to "get sample rate" do
|
194
|
-
rate_pointer = FFI::MemoryPointer.new(:int)
|
195
|
-
dir_pointer = FFI::MemoryPointer.new(:int)
|
196
|
-
dir_pointer.write_int(0)
|
197
|
-
|
198
|
-
error_code = ALSA::PCM::Native::hw_params_get_rate self.handle, rate_pointer, dir_pointer
|
199
|
-
|
200
|
-
rate = rate_pointer.read_int
|
201
|
-
|
202
|
-
rate_pointer.free
|
203
|
-
dir_pointer.free
|
204
|
-
|
205
|
-
error_code
|
206
|
-
end
|
207
|
-
rate
|
208
|
-
end
|
209
|
-
|
210
|
-
def sample_format=(sample_format)
|
211
|
-
ALSA::try_to "set sample format" do
|
212
|
-
ALSA::PCM::Native::hw_params_set_format self.device.handle, self.handle, ALSA::PCM::Native::Format.const_get(sample_format.to_s.upcase)
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def sample_format
|
217
|
-
format = nil
|
218
|
-
FFI::MemoryPointer.new(:int) do |format_pointer|
|
219
|
-
ALSA::try_to "get sample format" do
|
220
|
-
ALSA::PCM::Native::hw_params_get_format self.handle, format_pointer
|
221
|
-
end
|
222
|
-
format = format_pointer.read_int
|
223
|
-
end
|
224
|
-
format
|
225
|
-
end
|
226
|
-
|
227
|
-
def channels
|
228
|
-
channels = nil
|
229
|
-
FFI::MemoryPointer.new(:int) do |channels_pointer|
|
230
|
-
ALSA::try_to "get channels" do
|
231
|
-
ALSA::PCM::Native::hw_params_get_channels self.handle, channels_pointer
|
232
|
-
end
|
233
|
-
channels = channels_pointer.read_int
|
234
|
-
end
|
235
|
-
channels
|
236
|
-
end
|
237
|
-
|
238
|
-
def buffer_size_for(frame_count)
|
239
|
-
ALSA::PCM::Native::format_size(self.sample_format, frame_count) * self.channels
|
240
|
-
end
|
241
|
-
|
242
|
-
def free
|
243
|
-
ALSA::try_to "unallocate hw_params" do
|
244
|
-
ALSA::PCM::Native::hw_params_free self.handle
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
end
|
249
|
-
|
250
|
-
end
|
251
|
-
|
252
|
-
module Native
|
253
|
-
extend FFI::Library
|
254
|
-
ffi_lib "libasound.so"
|
255
|
-
|
256
|
-
STREAM_CAPTURE = 1
|
257
|
-
BLOCK = 0
|
258
|
-
attach_function :open, :snd_pcm_open, [:pointer, :string, :int, :int], :int
|
259
|
-
attach_function :prepare, :snd_pcm_prepare, [ :pointer ], :int
|
260
|
-
attach_function :close, :snd_pcm_close, [:pointer], :int
|
261
|
-
|
262
|
-
attach_function :readi, :snd_pcm_readi, [ :pointer, :pointer, :ulong ], :long
|
263
|
-
|
264
|
-
attach_function :pcm_recover, :snd_pcm_recover, [ :pointer, :int, :int ], :int
|
265
|
-
|
266
|
-
attach_function :hw_params_malloc, :snd_pcm_hw_params_malloc, [:pointer], :int
|
267
|
-
attach_function :hw_params_free, :snd_pcm_hw_params_free, [:pointer], :int
|
268
|
-
|
269
|
-
attach_function :hw_params, :snd_pcm_hw_params, [ :pointer, :pointer ], :int
|
270
|
-
attach_function :hw_params_any, :snd_pcm_hw_params_any, [:pointer, :pointer], :int
|
271
|
-
attach_function :hw_params_current, :snd_pcm_hw_params_current, [ :pointer, :pointer ], :int
|
272
|
-
|
273
|
-
|
274
|
-
module Access
|
275
|
-
MMAP_INTERLEAVED = 0
|
276
|
-
MMAP_NONINTERLEAVED = 1
|
277
|
-
MMAP_COMPLEX = 2
|
278
|
-
RW_INTERLEAVED = 3
|
279
|
-
RW_NONINTERLEAVED = 4
|
280
|
-
end
|
281
|
-
|
282
|
-
attach_function :hw_params_set_access, :snd_pcm_hw_params_set_access, [ :pointer, :pointer, :int ], :int
|
283
|
-
|
284
|
-
module Format
|
285
|
-
S16_LE = 2
|
286
|
-
end
|
287
|
-
|
288
|
-
attach_function :hw_params_set_format, :snd_pcm_hw_params_set_format, [ :pointer, :pointer, :int ], :int
|
289
|
-
attach_function :hw_params_get_format, :snd_pcm_hw_params_get_format, [ :pointer, :pointer ], :int
|
290
|
-
attach_function :hw_params_get_rate, :snd_pcm_hw_params_get_rate, [ :pointer, :pointer, :pointer ], :int
|
291
|
-
attach_function :hw_params_set_rate_near, :snd_pcm_hw_params_set_rate_near, [ :pointer, :pointer, :pointer, :pointer ], :int
|
292
|
-
attach_function :hw_params_set_channels, :snd_pcm_hw_params_set_channels, [ :pointer, :pointer, :uint ], :int
|
293
|
-
attach_function :hw_params_get_channels, :snd_pcm_hw_params_get_format, [ :pointer, :pointer ], :int
|
294
|
-
attach_function :hw_params_set_periods, :snd_pcm_hw_params_set_periods, [ :pointer, :pointer, :uint, :int ], :int
|
295
|
-
|
296
|
-
attach_function :format_size, :snd_pcm_format_size, [ :int, :uint ], :int
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|