hornetseye-alsa 0.1.2 → 0.2.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.
- data/Rakefile +14 -14
- data/ext/alsainput.cc +193 -0
- data/ext/alsainput.hh +57 -0
- data/ext/alsaoutput.cc +4 -17
- data/ext/alsaoutput.hh +1 -4
- data/ext/init.cc +2 -0
- data/lib/hornetseye-alsa/alsainput.rb +43 -0
- data/lib/hornetseye-alsa/alsaoutput.rb +1 -1
- data/lib/hornetseye_alsa_ext.rb +1 -0
- metadata +6 -3
data/Rakefile
CHANGED
@@ -7,15 +7,15 @@ require 'rake/loaders/makefile'
|
|
7
7
|
require 'rbconfig'
|
8
8
|
|
9
9
|
PKG_NAME = 'hornetseye-alsa'
|
10
|
-
PKG_VERSION = '0.
|
10
|
+
PKG_VERSION = '0.2.0'
|
11
|
+
CFG = RbConfig::CONFIG
|
11
12
|
CXX = ENV[ 'CXX' ] || 'g++'
|
12
|
-
STRIP = ENV[ 'STRIP' ] || 'strip'
|
13
13
|
RB_FILES = FileList[ 'lib/**/*.rb' ]
|
14
14
|
CC_FILES = FileList[ 'ext/*.cc' ]
|
15
15
|
HH_FILES = FileList[ 'ext/*.hh' ] + FileList[ 'ext/*.tcc' ]
|
16
16
|
TC_FILES = FileList[ 'test/tc_*.rb' ]
|
17
17
|
TS_FILES = FileList[ 'test/ts_*.rb' ]
|
18
|
-
SO_FILE = "ext/#{PKG_NAME.tr '\-', '_'}
|
18
|
+
SO_FILE = "ext/#{PKG_NAME.tr '\-', '_'}.#{CFG[ 'DLEXT' ]}"
|
19
19
|
PKG_FILES = [ 'Rakefile', 'README.md', 'COPYING', '.document' ] +
|
20
20
|
RB_FILES + CC_FILES + HH_FILES + TS_FILES + TC_FILES
|
21
21
|
BIN_FILES = [ 'README.md', 'COPYING', '.document', SO_FILE ] +
|
@@ -27,17 +27,18 @@ EMAIL = %q{jan@wedesoft.de}
|
|
27
27
|
HOMEPAGE = %q{http://wedesoft.github.com/hornetseye-alsa/}
|
28
28
|
|
29
29
|
OBJ = CC_FILES.ext 'o'
|
30
|
-
$CXXFLAGS =
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
"-I#{RbConfig::CONFIG[ 'rubyhdrdir' ]}/#{RbConfig::CONFIG[ 'arch' ]}"
|
30
|
+
$CXXFLAGS = "-DNDEBUG #{CFG[ 'CPPFLAGS' ]} #{CFG[ 'CFLAGS' ]}"
|
31
|
+
if CFG[ 'rubyhdrdir' ]
|
32
|
+
$CXXFLAGS = "#{$CXXFLAGS} -I#{CFG[ 'rubyhdrdir' ]} " +
|
33
|
+
"-I#{CFG[ 'rubyhdrdir' ]}/#{CFG[ 'arch' ]}"
|
35
34
|
else
|
36
|
-
$CXXFLAGS
|
35
|
+
$CXXFLAGS = "#{$CXXFLAGS} -I#{CFG[ 'archdir' ]}"
|
37
36
|
end
|
38
|
-
$LIBRUBYARG =
|
39
|
-
|
40
|
-
$
|
37
|
+
$LIBRUBYARG = "-L#{CFG[ 'libdir' ]} #{CFG[ 'LIBRUBYARG' ]} #{CFG[ 'LDFLAGS' ]} " +
|
38
|
+
"#{CFG[ 'SOLIBS' ]} #{CFG[ 'DLDLIBS' ]}"
|
39
|
+
$SITELIBDIR = CFG[ 'sitelibdir' ]
|
40
|
+
$SITEARCHDIR = CFG[ 'sitearchdir' ]
|
41
|
+
$LDSHARED = CFG[ 'LDSHARED' ][ CFG[ 'LDSHARED' ].index( ' ' ) .. -1 ]
|
41
42
|
|
42
43
|
task :default => :all
|
43
44
|
|
@@ -46,7 +47,6 @@ task :all => [ SO_FILE ]
|
|
46
47
|
|
47
48
|
file SO_FILE => OBJ do |t|
|
48
49
|
sh "#{CXX} -shared -o #{t.name} #{OBJ} -lasound #{$LIBRUBYARG}"
|
49
|
-
sh "#{STRIP} --strip-all #{t.name}"
|
50
50
|
end
|
51
51
|
|
52
52
|
task :test => [ SO_FILE ]
|
@@ -169,7 +169,7 @@ rule '.o' => '.cc' do |t|
|
|
169
169
|
end
|
170
170
|
|
171
171
|
file ".depends.mf" do |t|
|
172
|
-
sh "g++ -MM #{
|
172
|
+
sh "g++ -MM #{CC_FILES.join ' '} | " +
|
173
173
|
"sed -e :a -e N -e 's/\\n/\\$/g' -e ta | " +
|
174
174
|
"sed -e 's/ *\\\\\\$ */ /g' -e 's/\\$/\\n/g' | sed -e 's/^/ext\\//' > #{t.name}"
|
175
175
|
end
|
data/ext/alsainput.cc
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
/* HornetsEye - Computer Vision with Ruby
|
2
|
+
Copyright (C) 2006, 2007, 2008, 2009, 2010 Jan Wedekind
|
3
|
+
|
4
|
+
This program is free software: you can redistribute it and/or modify
|
5
|
+
it under the terms of the GNU General Public License as published by
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
7
|
+
(at your option) any later version.
|
8
|
+
|
9
|
+
This program is distributed in the hope that it will be useful,
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
GNU General Public License for more details.
|
13
|
+
|
14
|
+
You should have received a copy of the GNU General Public License
|
15
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
16
|
+
#include "alsainput.hh"
|
17
|
+
|
18
|
+
using namespace std;
|
19
|
+
|
20
|
+
VALUE AlsaInput::cRubyClass = Qnil;
|
21
|
+
|
22
|
+
AlsaInput::AlsaInput( const string &pcmName, unsigned int rate,
|
23
|
+
unsigned int channels, int periods,
|
24
|
+
snd_pcm_uframes_t frames ) throw (Error):
|
25
|
+
m_pcmHandle(NULL), m_pcmName( pcmName ), m_rate( rate ), m_channels( channels )
|
26
|
+
{
|
27
|
+
try {
|
28
|
+
snd_pcm_hw_params_t *hwParams;
|
29
|
+
snd_pcm_hw_params_alloca( &hwParams );
|
30
|
+
int err = snd_pcm_open( &m_pcmHandle, m_pcmName.c_str(), SND_PCM_STREAM_CAPTURE,
|
31
|
+
0 );
|
32
|
+
ERRORMACRO( err >= 0, Error, , "Error opening PCM device \"" << m_pcmName
|
33
|
+
<< "\": " << snd_strerror( err ) );
|
34
|
+
err = snd_pcm_hw_params_any( m_pcmHandle, hwParams );
|
35
|
+
ERRORMACRO( err >= 0, Error, , "Unable to configure the PCM device \""
|
36
|
+
<< m_pcmName << "\": " << snd_strerror( err ) );
|
37
|
+
err = snd_pcm_hw_params_set_access( m_pcmHandle, hwParams,
|
38
|
+
SND_PCM_ACCESS_RW_INTERLEAVED );
|
39
|
+
ERRORMACRO( err >= 0, Error, , "Error setting PCM device \""
|
40
|
+
<< m_pcmName << "\" to interlaced access: " << snd_strerror( err ) );
|
41
|
+
err = snd_pcm_hw_params_set_format( m_pcmHandle, hwParams,
|
42
|
+
SND_PCM_FORMAT_S16_LE );
|
43
|
+
ERRORMACRO( err >= 0, Error, , "Error setting PCM device \"" << m_pcmName
|
44
|
+
<< "\" to 16-bit signed integer format: " << snd_strerror( err ) );
|
45
|
+
err = snd_pcm_hw_params_set_rate_near( m_pcmHandle, hwParams, &m_rate, 0 );
|
46
|
+
ERRORMACRO( err >= 0, Error, , "Error setting sampling rate of PCM device \""
|
47
|
+
<< m_pcmName << "\" to " << rate << " Hz: " << snd_strerror( err ) );
|
48
|
+
err = snd_pcm_hw_params_set_channels( m_pcmHandle, hwParams, channels );
|
49
|
+
ERRORMACRO( err >= 0, Error, , "Error setting number of channels of PCM device \""
|
50
|
+
<< m_pcmName << "\" to " << channels << ": " << snd_strerror( err ) );
|
51
|
+
err = snd_pcm_hw_params_set_periods( m_pcmHandle, hwParams, periods, 0 );
|
52
|
+
ERRORMACRO( err >= 0, Error, , "Error setting number of periods of PCM device \""
|
53
|
+
<< m_pcmName << "\" to " << periods << ": " << snd_strerror( err ) );
|
54
|
+
err = snd_pcm_hw_params_set_buffer_size_near( m_pcmHandle, hwParams, &frames );
|
55
|
+
ERRORMACRO( err >= 0, Error, , "Error setting buffer size of PCM device \""
|
56
|
+
<< m_pcmName << "\" to " << frames << " frames: "
|
57
|
+
<< snd_strerror( err ) );
|
58
|
+
err = snd_pcm_hw_params( m_pcmHandle, hwParams );
|
59
|
+
ERRORMACRO( err >= 0, Error, , "Error setting parameters of PCM device \""
|
60
|
+
<< m_pcmName << "\": " << snd_strerror( err ) );
|
61
|
+
} catch ( Error &e ) {
|
62
|
+
close();
|
63
|
+
throw e;
|
64
|
+
};
|
65
|
+
}
|
66
|
+
|
67
|
+
AlsaInput::~AlsaInput(void)
|
68
|
+
{
|
69
|
+
close();
|
70
|
+
}
|
71
|
+
|
72
|
+
void AlsaInput::close(void)
|
73
|
+
{
|
74
|
+
if ( m_pcmHandle != NULL ) {
|
75
|
+
// drop();
|
76
|
+
snd_pcm_close( m_pcmHandle );
|
77
|
+
m_pcmHandle = NULL;
|
78
|
+
};
|
79
|
+
}
|
80
|
+
|
81
|
+
SequencePtr AlsaInput::read( int samples ) throw (Error)
|
82
|
+
{
|
83
|
+
ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
|
84
|
+
<< "\" is not open. Did you call \"close\" before?" );
|
85
|
+
SequencePtr frame( new Sequence( (int)( samples * 2 * m_channels ) ) );
|
86
|
+
int err;
|
87
|
+
while ( ( err = snd_pcm_readi( m_pcmHandle, (short int *)frame->data(),
|
88
|
+
samples ) ) < 0 ) {
|
89
|
+
err = snd_pcm_recover( m_pcmHandle, err, 1 );
|
90
|
+
ERRORMACRO( err >= 0, Error, , "Error reading audio frames from PCM device \""
|
91
|
+
<< m_pcmName << "\": " << snd_strerror( err ) );
|
92
|
+
};
|
93
|
+
ERRORMACRO( samples == err, Error, , "Only managed to read " << err << " of "
|
94
|
+
<< samples << " frames from PCM device \"" << m_pcmName << "\"" );
|
95
|
+
return frame;
|
96
|
+
}
|
97
|
+
|
98
|
+
unsigned int AlsaInput::rate(void)
|
99
|
+
{
|
100
|
+
return m_rate;
|
101
|
+
}
|
102
|
+
|
103
|
+
unsigned int AlsaInput::channels(void)
|
104
|
+
{
|
105
|
+
return m_channels;
|
106
|
+
}
|
107
|
+
|
108
|
+
void AlsaInput::prepare(void) throw (Error)
|
109
|
+
{
|
110
|
+
ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
|
111
|
+
<< "\" is not open. Did you call \"close\" before?" );
|
112
|
+
int err = snd_pcm_prepare( m_pcmHandle );
|
113
|
+
ERRORMACRO( err >= 0, Error, , "Error preparing PCM device \"" << m_pcmName
|
114
|
+
<< "\": " << snd_strerror( err ) );
|
115
|
+
}
|
116
|
+
|
117
|
+
VALUE AlsaInput::registerRubyClass( VALUE rbModule )
|
118
|
+
{
|
119
|
+
cRubyClass = rb_define_class_under( rbModule, "AlsaInput", rb_cObject );
|
120
|
+
rb_define_singleton_method( cRubyClass, "new",
|
121
|
+
RUBY_METHOD_FUNC( wrapNew ), 5 );
|
122
|
+
rb_define_method( cRubyClass, "close", RUBY_METHOD_FUNC( wrapClose ), 0 );
|
123
|
+
rb_define_method( cRubyClass, "read", RUBY_METHOD_FUNC( wrapRead ), 1 );
|
124
|
+
rb_define_method( cRubyClass, "rate", RUBY_METHOD_FUNC( wrapRate ), 0 );
|
125
|
+
rb_define_method( cRubyClass, "channels", RUBY_METHOD_FUNC( wrapChannels ), 0 );
|
126
|
+
rb_define_method( cRubyClass, "prepare", RUBY_METHOD_FUNC( wrapPrepare ), 0 );
|
127
|
+
}
|
128
|
+
|
129
|
+
void AlsaInput::deleteRubyObject( void *ptr )
|
130
|
+
{
|
131
|
+
delete (AlsaInputPtr *)ptr;
|
132
|
+
}
|
133
|
+
|
134
|
+
VALUE AlsaInput::wrapNew( VALUE rbClass, VALUE rbPCMName, VALUE rbRate,
|
135
|
+
VALUE rbChannels, VALUE rbPeriods, VALUE rbFrames )
|
136
|
+
{
|
137
|
+
VALUE retVal = Qnil;
|
138
|
+
try {
|
139
|
+
rb_check_type( rbPCMName, T_STRING );
|
140
|
+
AlsaInputPtr ptr( new AlsaInput( StringValuePtr( rbPCMName ),
|
141
|
+
NUM2UINT( rbRate ), NUM2UINT( rbChannels ),
|
142
|
+
NUM2INT( rbPeriods ), NUM2INT( rbFrames ) ) );
|
143
|
+
retVal = Data_Wrap_Struct( rbClass, 0, deleteRubyObject,
|
144
|
+
new AlsaInputPtr( ptr ) );
|
145
|
+
} catch ( exception &e ) {
|
146
|
+
rb_raise( rb_eRuntimeError, "%s", e.what() );
|
147
|
+
};
|
148
|
+
return retVal;
|
149
|
+
}
|
150
|
+
|
151
|
+
VALUE AlsaInput::wrapClose( VALUE rbSelf )
|
152
|
+
{
|
153
|
+
AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
|
154
|
+
(*self)->close();
|
155
|
+
return rbSelf;
|
156
|
+
}
|
157
|
+
|
158
|
+
VALUE AlsaInput::wrapRead( VALUE rbSelf, VALUE rbSamples )
|
159
|
+
{
|
160
|
+
VALUE rbRetVal = Qnil;
|
161
|
+
try {
|
162
|
+
AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
|
163
|
+
SequencePtr sequence( (*self)->read( NUM2INT( rbSamples ) ) );
|
164
|
+
rbRetVal = sequence->rubyObject();
|
165
|
+
} catch ( exception &e ) {
|
166
|
+
rb_raise( rb_eRuntimeError, "%s", e.what() );
|
167
|
+
};
|
168
|
+
return rbRetVal;
|
169
|
+
}
|
170
|
+
|
171
|
+
VALUE AlsaInput::wrapRate( VALUE rbSelf )
|
172
|
+
{
|
173
|
+
AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
|
174
|
+
return UINT2NUM( (*self)->rate() );
|
175
|
+
}
|
176
|
+
|
177
|
+
VALUE AlsaInput::wrapChannels( VALUE rbSelf )
|
178
|
+
{
|
179
|
+
AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
|
180
|
+
return UINT2NUM( (*self)->channels() );
|
181
|
+
}
|
182
|
+
|
183
|
+
VALUE AlsaInput::wrapPrepare( VALUE rbSelf )
|
184
|
+
{
|
185
|
+
try {
|
186
|
+
AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
|
187
|
+
(*self)->prepare();
|
188
|
+
} catch ( exception &e ) {
|
189
|
+
rb_raise( rb_eRuntimeError, "%s", e.what() );
|
190
|
+
};
|
191
|
+
return rbSelf;
|
192
|
+
}
|
193
|
+
|
data/ext/alsainput.hh
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
/* HornetsEye - Computer Vision with Ruby
|
2
|
+
Copyright (C) 2006, 2007, 2008, 2009, 2010 Jan Wedekind
|
3
|
+
|
4
|
+
This program is free software: you can redistribute it and/or modify
|
5
|
+
it under the terms of the GNU General Public License as published by
|
6
|
+
the Free Software Foundation, either version 3 of the License, or
|
7
|
+
(at your option) any later version.
|
8
|
+
|
9
|
+
This program is distributed in the hope that it will be useful,
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
GNU General Public License for more details.
|
13
|
+
|
14
|
+
You should have received a copy of the GNU General Public License
|
15
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
16
|
+
#ifndef ALSAINPUT_HH
|
17
|
+
#define ALSAINPUT_HH
|
18
|
+
|
19
|
+
#include <alsa/asoundlib.h>
|
20
|
+
#include <string>
|
21
|
+
#include "rubyinc.hh"
|
22
|
+
#include "error.hh"
|
23
|
+
#include "sequence.hh"
|
24
|
+
|
25
|
+
class AlsaInput
|
26
|
+
{
|
27
|
+
public:
|
28
|
+
AlsaInput( const std::string &pcmName = "default:0",
|
29
|
+
unsigned int rate = 48000, unsigned int channels = 2,
|
30
|
+
int periods = 16, snd_pcm_uframes_t frames = 1024 ) throw (Error);
|
31
|
+
virtual ~AlsaInput(void);
|
32
|
+
void close(void);
|
33
|
+
SequencePtr read( int samples ) throw (Error);
|
34
|
+
unsigned int rate(void);
|
35
|
+
unsigned int channels(void);
|
36
|
+
void prepare(void) throw (Error);
|
37
|
+
static VALUE cRubyClass;
|
38
|
+
static VALUE registerRubyClass( VALUE rbModule );
|
39
|
+
static void deleteRubyObject( void *ptr );
|
40
|
+
static VALUE wrapNew( VALUE rbClass, VALUE rbPCMName, VALUE rbRate,
|
41
|
+
VALUE rbChannels, VALUE rbPeriods, VALUE rbFrames );
|
42
|
+
static VALUE wrapClose( VALUE rbSelf );
|
43
|
+
static VALUE wrapRead( VALUE rbSelf, VALUE rbSamples );
|
44
|
+
static VALUE wrapRate( VALUE rbSelf );
|
45
|
+
static VALUE wrapChannels( VALUE rbSelf );
|
46
|
+
static VALUE wrapPrepare( VALUE rbSelf );
|
47
|
+
protected:
|
48
|
+
snd_pcm_t *m_pcmHandle;
|
49
|
+
std::string m_pcmName;
|
50
|
+
unsigned int m_rate;
|
51
|
+
unsigned int m_channels;
|
52
|
+
};
|
53
|
+
|
54
|
+
typedef boost::shared_ptr< AlsaInput > AlsaInputPtr;
|
55
|
+
|
56
|
+
#endif
|
57
|
+
|
data/ext/alsaoutput.cc
CHANGED
@@ -21,9 +21,8 @@ VALUE AlsaOutput::cRubyClass = Qnil;
|
|
21
21
|
|
22
22
|
AlsaOutput::AlsaOutput( const string &pcmName, unsigned int rate,
|
23
23
|
unsigned int channels, int periods,
|
24
|
-
|
25
|
-
m_pcmHandle(NULL), m_pcmName( pcmName ), m_rate( rate ), m_channels( channels )
|
26
|
-
m_frames( frames )
|
24
|
+
snd_pcm_uframes_t frames ) throw (Error):
|
25
|
+
m_pcmHandle(NULL), m_pcmName( pcmName ), m_rate( rate ), m_channels( channels )
|
27
26
|
{
|
28
27
|
try {
|
29
28
|
snd_pcm_hw_params_t *hwParams;
|
@@ -52,9 +51,9 @@ AlsaOutput::AlsaOutput( const string &pcmName, unsigned int rate,
|
|
52
51
|
err = snd_pcm_hw_params_set_periods( m_pcmHandle, hwParams, periods, 0 );
|
53
52
|
ERRORMACRO( err >= 0, Error, , "Error setting number of periods of PCM device \""
|
54
53
|
<< m_pcmName << "\" to " << periods << ": " << snd_strerror( err ) );
|
55
|
-
err = snd_pcm_hw_params_set_buffer_size_near( m_pcmHandle, hwParams, &
|
54
|
+
err = snd_pcm_hw_params_set_buffer_size_near( m_pcmHandle, hwParams, &frames );
|
56
55
|
ERRORMACRO( err >= 0, Error, , "Error setting buffer size of PCM device \""
|
57
|
-
<< m_pcmName << "\" to " <<
|
56
|
+
<< m_pcmName << "\" to " << frames << " frames: "
|
58
57
|
<< snd_strerror( err ) );
|
59
58
|
err = snd_pcm_hw_params( m_pcmHandle, hwParams );
|
60
59
|
ERRORMACRO( err >= 0, Error, , "Error setting parameters of PCM device \""
|
@@ -119,11 +118,6 @@ unsigned int AlsaOutput::channels(void)
|
|
119
118
|
return m_channels;
|
120
119
|
}
|
121
120
|
|
122
|
-
unsigned int AlsaOutput::frames(void)
|
123
|
-
{
|
124
|
-
return m_frames;
|
125
|
-
}
|
126
|
-
|
127
121
|
int AlsaOutput::avail(void) throw (Error)
|
128
122
|
{
|
129
123
|
ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
|
@@ -174,7 +168,6 @@ VALUE AlsaOutput::registerRubyClass( VALUE rbModule )
|
|
174
168
|
rb_define_method( cRubyClass, "drain", RUBY_METHOD_FUNC( wrapDrain ), 0 );
|
175
169
|
rb_define_method( cRubyClass, "rate", RUBY_METHOD_FUNC( wrapRate ), 0 );
|
176
170
|
rb_define_method( cRubyClass, "channels", RUBY_METHOD_FUNC( wrapChannels ), 0 );
|
177
|
-
rb_define_method( cRubyClass, "frames", RUBY_METHOD_FUNC( wrapFrames ), 0 );
|
178
171
|
rb_define_method( cRubyClass, "avail", RUBY_METHOD_FUNC( wrapAvail ), 0 );
|
179
172
|
rb_define_method( cRubyClass, "delay", RUBY_METHOD_FUNC( wrapDelay ), 0 );
|
180
173
|
rb_define_method( cRubyClass, "prepare", RUBY_METHOD_FUNC( wrapPrepare ), 0 );
|
@@ -255,12 +248,6 @@ VALUE AlsaOutput::wrapChannels( VALUE rbSelf )
|
|
255
248
|
return UINT2NUM( (*self)->channels() );
|
256
249
|
}
|
257
250
|
|
258
|
-
VALUE AlsaOutput::wrapFrames( VALUE rbSelf )
|
259
|
-
{
|
260
|
-
AlsaOutputPtr *self; Data_Get_Struct( rbSelf, AlsaOutputPtr, self );
|
261
|
-
return UINT2NUM( (*self)->frames() );
|
262
|
-
}
|
263
|
-
|
264
251
|
VALUE AlsaOutput::wrapAvail( VALUE rbSelf )
|
265
252
|
{
|
266
253
|
VALUE rbRetVal = Qnil;
|
data/ext/alsaoutput.hh
CHANGED
@@ -27,7 +27,7 @@ class AlsaOutput
|
|
27
27
|
public:
|
28
28
|
AlsaOutput( const std::string &pcmName = "default:0",
|
29
29
|
unsigned int rate = 48000, unsigned int channels = 2,
|
30
|
-
int periods =
|
30
|
+
int periods = 16, snd_pcm_uframes_t frames = 1024 ) throw (Error);
|
31
31
|
virtual ~AlsaOutput(void);
|
32
32
|
void close(void);
|
33
33
|
void write( SequencePtr sequence ) throw (Error);
|
@@ -35,7 +35,6 @@ public:
|
|
35
35
|
void drain(void) throw (Error);
|
36
36
|
unsigned int rate(void);
|
37
37
|
unsigned int channels(void);
|
38
|
-
unsigned int frames(void);
|
39
38
|
int avail(void) throw (Error);
|
40
39
|
int delay(void) throw (Error);
|
41
40
|
void prepare(void) throw (Error);
|
@@ -50,7 +49,6 @@ public:
|
|
50
49
|
static VALUE wrapDrain( VALUE rbSelf );
|
51
50
|
static VALUE wrapRate( VALUE rbSelf );
|
52
51
|
static VALUE wrapChannels( VALUE rbSelf );
|
53
|
-
static VALUE wrapFrames( VALUE rbSelf );
|
54
52
|
static VALUE wrapAvail( VALUE rbSelf );
|
55
53
|
static VALUE wrapDelay( VALUE rbSelf );
|
56
54
|
static VALUE wrapPrepare( VALUE rbSelf );
|
@@ -59,7 +57,6 @@ protected:
|
|
59
57
|
std::string m_pcmName;
|
60
58
|
unsigned int m_rate;
|
61
59
|
unsigned int m_channels;
|
62
|
-
snd_pcm_uframes_t m_frames;
|
63
60
|
};
|
64
61
|
|
65
62
|
typedef boost::shared_ptr< AlsaOutput > AlsaOutputPtr;
|
data/ext/init.cc
CHANGED
@@ -14,6 +14,7 @@
|
|
14
14
|
You should have received a copy of the GNU General Public License
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
16
16
|
#include "alsaoutput.hh"
|
17
|
+
#include "alsainput.hh"
|
17
18
|
|
18
19
|
#ifdef WIN32
|
19
20
|
#define DLLEXPORT __declspec(dllexport)
|
@@ -32,6 +33,7 @@ extern "C" {
|
|
32
33
|
rb_require( "multiarray" );
|
33
34
|
VALUE rbHornetseye = rb_define_module( "Hornetseye" );
|
34
35
|
AlsaOutput::registerRubyClass( rbHornetseye );
|
36
|
+
AlsaInput::registerRubyClass( rbHornetseye );
|
35
37
|
rb_require( "hornetseye_alsa_ext.rb" );
|
36
38
|
}
|
37
39
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# hornetseye-alsa - Play audio data using libalsa
|
2
|
+
# Copyright (C) 2010 Jan Wedekind
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
# Namespace of Hornetseye computer vision library
|
18
|
+
module Hornetseye
|
19
|
+
|
20
|
+
class AlsaInput
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
alias_method :orig_new, :new
|
25
|
+
|
26
|
+
def new( pcm_name = 'default:0', rate = 48000, channels = 2, periods = 16,
|
27
|
+
frames = 1024 )
|
28
|
+
orig_new pcm_name, rate, channels, periods, frames
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
alias_method :orig_read, :read
|
34
|
+
|
35
|
+
def read( samples )
|
36
|
+
Hornetseye::MultiArray( SINT, channels, samples ).
|
37
|
+
new orig_read( samples ).memory
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
@@ -43,7 +43,7 @@ module Hornetseye
|
|
43
43
|
raise "Audio frame must have #{channels} channel(s) but had " +
|
44
44
|
"#{frame.shape.first}"
|
45
45
|
end
|
46
|
-
orig_write Sequence( UBYTE, 2 * frame.size ).new( frame.memory )
|
46
|
+
orig_write Hornetseye::Sequence( UBYTE, 2 * frame.size ).new( frame.memory )
|
47
47
|
end
|
48
48
|
|
49
49
|
end
|
data/lib/hornetseye_alsa_ext.rb
CHANGED
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
- 1
|
8
7
|
- 2
|
9
|
-
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jan Wedekind
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-11-15 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -71,12 +71,15 @@ files:
|
|
71
71
|
- README.md
|
72
72
|
- COPYING
|
73
73
|
- .document
|
74
|
+
- lib/hornetseye-alsa/alsainput.rb
|
74
75
|
- lib/hornetseye-alsa/alsaoutput.rb
|
75
76
|
- lib/hornetseye_alsa_ext.rb
|
77
|
+
- ext/alsainput.cc
|
76
78
|
- ext/init.cc
|
77
79
|
- ext/sequence.cc
|
78
80
|
- ext/alsaoutput.cc
|
79
81
|
- ext/sequence.hh
|
82
|
+
- ext/alsainput.hh
|
80
83
|
- ext/rubyinc.hh
|
81
84
|
- ext/error.hh
|
82
85
|
- ext/alsaoutput.hh
|