hornetseye-alsa 1.0.0 → 1.1.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/COPYING CHANGED
@@ -1,5 +1,5 @@
1
1
  This is the license for the computer vision library Hornetseye.
2
- Copyright (C) 2006 - 2010 Jan Wedekind, Sheffield, United Kingdom.
2
+ Copyright (C) 2006 - 2012 Jan Wedekind, Sheffield, United Kingdom.
3
3
 
4
4
 
5
5
  GNU GENERAL PUBLIC LICENSE
data/README.md CHANGED
@@ -2,7 +2,7 @@ hornetseye-alsa
2
2
  ===============
3
3
 
4
4
  **Author**: Jan Wedekind
5
- **Copyright**: 2010
5
+ **Copyright**: 2012
6
6
  **License**: GPL
7
7
 
8
8
  Synopsis
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require 'rake/loaders/makefile'
7
7
  require 'rbconfig'
8
8
 
9
9
  PKG_NAME = 'hornetseye-alsa'
10
- PKG_VERSION = '1.0.0'
10
+ PKG_VERSION = '1.1.0'
11
11
  CFG = RbConfig::CONFIG
12
12
  CXX = ENV[ 'CXX' ] || 'g++'
13
13
  RB_FILES = FileList[ 'lib/**/*.rb' ]
data/ext/alsaoutput.cc CHANGED
@@ -1,5 +1,5 @@
1
1
  /* HornetsEye - Computer Vision with Ruby
2
- Copyright (C) 2006, 2007, 2008, 2009, 2010 Jan Wedekind
2
+ Copyright (C) 2012 Jan Wedekind
3
3
 
4
4
  This program is free software: you can redistribute it and/or modify
5
5
  it under the terms of the GNU General Public License as published by
@@ -19,46 +19,52 @@ using namespace std;
19
19
 
20
20
  VALUE AlsaOutput::cRubyClass = Qnil;
21
21
 
22
- AlsaOutput::AlsaOutput( 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 )
22
+ AlsaOutput::AlsaOutput(const string &pcmName, unsigned int rate,
23
+ unsigned int channels) throw (Error):
24
+ m_pcmHandle(NULL), m_pcmName(pcmName), m_rate(rate), m_channels(channels),
25
+ m_periodSize(1024), m_threadInitialised(false), m_start(0), m_count(0),
26
+ m_size(rate)
26
27
  {
27
28
  try {
28
29
  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_PLAYBACK,
31
- 0 );// SND_PCM_NONBLOCK
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 ) );
30
+ snd_pcm_hw_params_alloca(&hwParams);
31
+ int err = snd_pcm_open(&m_pcmHandle, m_pcmName.c_str(), SND_PCM_STREAM_PLAYBACK,
32
+ 0);//SND_PCM_NONBLOCK);
33
+ ERRORMACRO(err >= 0, Error, , "Error opening PCM device \"" << m_pcmName
34
+ << "\": " << snd_strerror(err));
35
+ err = snd_pcm_hw_params_any(m_pcmHandle, hwParams);
36
+ ERRORMACRO(err >= 0, Error, , "Unable to configure the PCM device \""
37
+ << m_pcmName << "\": " << snd_strerror(err));
38
+ err = snd_pcm_hw_params_set_access(m_pcmHandle, hwParams,
39
+ SND_PCM_ACCESS_RW_INTERLEAVED);
40
+ ERRORMACRO(err >= 0, Error, , "Error setting PCM device \""
41
+ << m_pcmName << "\" to interlaced access: " << snd_strerror(err));
42
+ err = snd_pcm_hw_params_set_format(m_pcmHandle, hwParams, 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
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 ) );
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
+ unsigned int bufferTime = 500000;
52
+ err = snd_pcm_hw_params_set_buffer_time_near(m_pcmHandle, hwParams, &bufferTime, NULL);
53
+ ERRORMACRO(err >= 0, Error, , "Error setting buffer time of PCM device \""
54
+ << m_pcmName << "\" to " << bufferTime << " us: " << snd_strerror(err));
55
+ unsigned int periods = 16;
56
+ err = snd_pcm_hw_params_set_periods_near(m_pcmHandle, hwParams, &periods, NULL);
57
+ ERRORMACRO(err >= 0, Error, , "Error setting periods of PCM device \""
58
+ << m_pcmName << "\" to " << periods << ": " << snd_strerror(err));
58
59
  err = snd_pcm_hw_params( m_pcmHandle, hwParams );
59
60
  ERRORMACRO( err >= 0, Error, , "Error setting parameters of PCM device \""
60
61
  << m_pcmName << "\": " << snd_strerror( err ) );
61
- } catch ( Error &e ) {
62
+ err = snd_pcm_hw_params_get_period_size(hwParams, &m_periodSize, NULL);
63
+ ERRORMACRO( err >= 0, Error, , "Error getting period size of PCM device \""
64
+ << m_pcmName << "\": " << snd_strerror( err ) );
65
+ err = pthread_mutex_init(&m_mutex, NULL);
66
+ ERRORMACRO(err == 0, Error, , "Error initialising mutex: " << strerror(err));
67
+ } catch (Error &e) {
62
68
  close();
63
69
  throw e;
64
70
  };
@@ -72,40 +78,71 @@ AlsaOutput::~AlsaOutput(void)
72
78
  void AlsaOutput::close(void)
73
79
  {
74
80
  if ( m_pcmHandle != NULL ) {
75
- drop();
81
+ drain();
82
+ pthread_mutex_destroy(&m_mutex);
76
83
  snd_pcm_close( m_pcmHandle );
77
84
  m_pcmHandle = NULL;
78
85
  };
79
86
  }
80
87
 
81
- void AlsaOutput::write( SequencePtr frame ) throw (Error)
88
+ void AlsaOutput::write(SequencePtr frame) throw (Error)
82
89
  {
83
- ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
84
- << "\" is not open. Did you call \"close\" before?" );
85
- int n = frame->size() / ( 2 * m_channels );
86
- int err;
87
- while ( ( err = snd_pcm_writei( m_pcmHandle, (short int *)frame->data(),
88
- n ) ) < 0 ) {
89
- err = snd_pcm_recover( m_pcmHandle, err, 1 );
90
- ERRORMACRO( err >= 0, Error, , "Error writing audio frames to PCM device \""
91
- << m_pcmName << "\": " << snd_strerror( err ) );
90
+ ERRORMACRO(m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
91
+ << "\" is not open. Did you call \"close\" before?");
92
+ int n = frame->size() / (2 * m_channels);
93
+ lock();
94
+ if (!m_data.get()) {
95
+ if (m_threadInitialised) pthread_detach(m_thread);
96
+ while(m_size < n) m_size = 2 * m_size;
97
+ m_data = boost::shared_array<short int>(new short int[m_size * m_channels]);
98
+ m_start = 0;
99
+ m_count = 0;
100
+ pthread_create(&m_thread, NULL, staticThreadFunc, this);
101
+ };
102
+ if (m_count + n > m_size) {
103
+ int m_size_new = m_size;
104
+ while(m_size_new < m_count + n) m_size_new = 2 * m_size_new;
105
+ boost::shared_array<short int> data(new short int[m_size_new * m_channels]);
106
+ if (m_start + m_count > m_size) {
107
+ memcpy(data.get(), m_data.get() + m_start * m_channels, (m_size - m_start) * 2 * m_channels);
108
+ memcpy(data.get() + (m_size - m_start) * m_channels, m_data.get(), (m_start + m_count - m_size) * 2 * m_channels);
109
+ } else
110
+ memcpy(data.get(), m_data.get() + m_start * m_channels, m_count * 2 * m_channels);
111
+ m_data = data;
112
+ m_start = 0;
113
+ m_size = m_size_new;
92
114
  };
93
- ERRORMACRO( n == err, Error, , "Only managed to write " << err << " of " << n
94
- << " frames to PCM device \"" << m_pcmName << "\"" );
115
+ int offset = m_start + m_count;
116
+ if (offset > m_size) offset -= m_size;
117
+ if (offset + n > m_size) {
118
+ memcpy(m_data.get() + offset * m_channels, frame->data(), (m_size - offset) * 2 * m_channels);
119
+ memcpy(m_data.get(), frame->data() + (m_size - offset) * m_channels, (n + m_size - offset) * 2 * m_channels);
120
+ } else
121
+ memcpy(m_data.get() + offset * m_channels, frame->data(), n * 2 * m_channels);
122
+ m_count += n;
123
+ unlock();
95
124
  }
96
125
 
97
126
  void AlsaOutput::drop(void) throw (Error)
98
127
  {
99
128
  ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
100
129
  << "\" is not open. Did you call \"close\" before?" );
101
- snd_pcm_drop( m_pcmHandle );
130
+ lock();
131
+ m_data.reset();
132
+ m_count = 0;
133
+ unlock();
134
+ snd_pcm_drop(m_pcmHandle);
102
135
  }
103
136
 
104
137
  void AlsaOutput::drain(void) throw (Error)
105
138
  {
106
- ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
107
- << "\" is not open. Did you call \"close\" before?" );
108
- snd_pcm_drain( m_pcmHandle );
139
+ if (m_threadInitialised) {
140
+ pthread_join(m_thread, NULL);
141
+ m_threadInitialised = false;
142
+ }
143
+ ERRORMACRO(m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
144
+ << "\" is not open. Did you call \"close\" before?");
145
+ snd_pcm_drain(m_pcmHandle);
109
146
  }
110
147
 
111
148
  unsigned int AlsaOutput::rate(void)
@@ -120,8 +157,6 @@ unsigned int AlsaOutput::channels(void)
120
157
 
121
158
  int AlsaOutput::avail(void) throw (Error)
122
159
  {
123
- ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
124
- << "\" is not open. Did you call \"close\" before?" );
125
160
  snd_pcm_sframes_t frames;
126
161
  int err = 0;
127
162
  while ( ( frames = snd_pcm_avail( m_pcmHandle ) ) < 0 ) {
@@ -135,42 +170,94 @@ int AlsaOutput::avail(void) throw (Error)
135
170
 
136
171
  int AlsaOutput::delay(void) throw (Error)
137
172
  {
138
- ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
139
- << "\" is not open. Did you call \"close\" before?" );
173
+ ERRORMACRO(m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
174
+ << "\" is not open. Did you call \"close\" before?");
175
+ lock();
140
176
  snd_pcm_sframes_t frames;
141
177
  int err;
142
- while ( ( err = snd_pcm_delay( m_pcmHandle, &frames ) ) < 0 ) {
143
- err = snd_pcm_recover( m_pcmHandle, err, 1 );
144
- ERRORMACRO( err >= 0, Error, , "Error querying number of available frames for "
145
- "update of PCM device \"" << m_pcmName << "\": "
146
- << snd_strerror( err ) );
178
+ while ((err = snd_pcm_delay(m_pcmHandle, &frames)) < 0) {
179
+ err = snd_pcm_recover(m_pcmHandle, err, 1);
180
+ if (err < 0) {
181
+ unlock();
182
+ ERRORMACRO(false, Error, , "Error querying number of available frames for "
183
+ "update of PCM device \"" << m_pcmName << "\": "
184
+ << snd_strerror(err));
185
+ };
147
186
  };
187
+ frames += m_count;
188
+ unlock();
148
189
  return frames;
149
190
  }
150
191
 
151
- void AlsaOutput::prepare(void) throw (Error)
192
+ void AlsaOutput::lock(void)
152
193
  {
153
- ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
154
- << "\" is not open. Did you call \"close\" before?" );
155
- int err = snd_pcm_prepare( m_pcmHandle );
156
- ERRORMACRO( err >= 0, Error, , "Error preparing PCM device \"" << m_pcmName
157
- << "\": " << snd_strerror( err ) );
194
+ pthread_mutex_lock( &m_mutex );
195
+ }
196
+
197
+ void AlsaOutput::unlock(void)
198
+ {
199
+ pthread_mutex_unlock( &m_mutex );
200
+ }
201
+
202
+ void AlsaOutput::writei(short int *data, int count) throw (Error)
203
+ {
204
+ int err;
205
+ while ((err = snd_pcm_writei(m_pcmHandle, data, count)) < 0) {
206
+ err = snd_pcm_recover(m_pcmHandle, err, 1);
207
+ ERRORMACRO(err >= 0, Error, , "Error writing audio frames to PCM device \""
208
+ << m_pcmName << "\": " << snd_strerror(err));
209
+ };
210
+ ERRORMACRO(count == err, Error, , "Only managed to write " << err << " of " << count
211
+ << " frames to PCM device \"" << m_pcmName << "\"");
212
+ }
213
+
214
+ void AlsaOutput::threadFunc(void)
215
+ {
216
+ bool quit = false;
217
+ while (!quit) {
218
+ try {
219
+ lock();
220
+ int n = m_periodSize;
221
+ if (n > m_count) n = m_count;
222
+ if (m_count <= 0) m_data.reset();
223
+ if (m_start >= m_size) m_start -= m_size;
224
+ if (m_data.get()) {
225
+ if (m_start + n > m_size) {
226
+ writei(m_data.get() + m_start * m_channels, m_size - m_start);
227
+ writei(m_data.get(), m_start + n - m_size);
228
+ } else {
229
+ writei(m_data.get() + m_start * m_channels, n);
230
+ };
231
+ m_start += n;
232
+ m_count -= n;
233
+ } else
234
+ quit = true;
235
+ unlock();
236
+ snd_pcm_wait(m_pcmHandle, 1000);
237
+ } catch (Error &e) {
238
+ quit = true;
239
+ unlock();
240
+ }
241
+ };
242
+ }
243
+
244
+ void *AlsaOutput::staticThreadFunc( void *self )
245
+ {
246
+ ((AlsaOutput *)self)->threadFunc();
247
+ return self;
158
248
  }
159
249
 
160
250
  VALUE AlsaOutput::registerRubyClass( VALUE rbModule )
161
251
  {
162
252
  cRubyClass = rb_define_class_under( rbModule, "AlsaOutput", rb_cObject );
163
- rb_define_singleton_method( cRubyClass, "new",
164
- RUBY_METHOD_FUNC( wrapNew ), 5 );
253
+ rb_define_singleton_method(cRubyClass, "new", RUBY_METHOD_FUNC(wrapNew), 3);
165
254
  rb_define_method( cRubyClass, "close", RUBY_METHOD_FUNC( wrapClose ), 0 );
166
255
  rb_define_method( cRubyClass, "write", RUBY_METHOD_FUNC( wrapWrite ), 1 );
167
256
  rb_define_method( cRubyClass, "drop", RUBY_METHOD_FUNC( wrapDrop ), 0 );
168
257
  rb_define_method( cRubyClass, "drain", RUBY_METHOD_FUNC( wrapDrain ), 0 );
169
258
  rb_define_method( cRubyClass, "rate", RUBY_METHOD_FUNC( wrapRate ), 0 );
170
259
  rb_define_method( cRubyClass, "channels", RUBY_METHOD_FUNC( wrapChannels ), 0 );
171
- rb_define_method( cRubyClass, "avail", RUBY_METHOD_FUNC( wrapAvail ), 0 );
172
260
  rb_define_method( cRubyClass, "delay", RUBY_METHOD_FUNC( wrapDelay ), 0 );
173
- rb_define_method( cRubyClass, "prepare", RUBY_METHOD_FUNC( wrapPrepare ), 0 );
174
261
  }
175
262
 
176
263
  void AlsaOutput::deleteRubyObject( void *ptr )
@@ -178,15 +265,13 @@ void AlsaOutput::deleteRubyObject( void *ptr )
178
265
  delete (AlsaOutputPtr *)ptr;
179
266
  }
180
267
 
181
- VALUE AlsaOutput::wrapNew( VALUE rbClass, VALUE rbPCMName, VALUE rbRate,
182
- VALUE rbChannels, VALUE rbPeriods, VALUE rbFrames )
268
+ VALUE AlsaOutput::wrapNew(VALUE rbClass, VALUE rbPCMName, VALUE rbRate, VALUE rbChannels)
183
269
  {
184
270
  VALUE retVal = Qnil;
185
271
  try {
186
272
  rb_check_type( rbPCMName, T_STRING );
187
- AlsaOutputPtr ptr( new AlsaOutput( StringValuePtr( rbPCMName ),
188
- NUM2UINT( rbRate ), NUM2UINT( rbChannels ),
189
- NUM2INT( rbPeriods ), NUM2INT( rbFrames ) ) );
273
+ AlsaOutputPtr ptr(new AlsaOutput(StringValuePtr(rbPCMName),
274
+ NUM2UINT(rbRate), NUM2UINT(rbChannels)));
190
275
  retVal = Data_Wrap_Struct( rbClass, 0, deleteRubyObject,
191
276
  new AlsaOutputPtr( ptr ) );
192
277
  } catch ( exception &e ) {
@@ -248,18 +333,6 @@ VALUE AlsaOutput::wrapChannels( VALUE rbSelf )
248
333
  return UINT2NUM( (*self)->channels() );
249
334
  }
250
335
 
251
- VALUE AlsaOutput::wrapAvail( VALUE rbSelf )
252
- {
253
- VALUE rbRetVal = Qnil;
254
- try {
255
- AlsaOutputPtr *self; Data_Get_Struct( rbSelf, AlsaOutputPtr, self );
256
- rbRetVal = INT2NUM( (*self)->avail() );
257
- } catch ( exception &e ) {
258
- rb_raise( rb_eRuntimeError, "%s", e.what() );
259
- };
260
- return rbRetVal;
261
- }
262
-
263
336
  VALUE AlsaOutput::wrapDelay( VALUE rbSelf )
264
337
  {
265
338
  VALUE rbRetVal = Qnil;
@@ -271,15 +344,3 @@ VALUE AlsaOutput::wrapDelay( VALUE rbSelf )
271
344
  };
272
345
  return rbRetVal;
273
346
  }
274
-
275
- VALUE AlsaOutput::wrapPrepare( VALUE rbSelf )
276
- {
277
- try {
278
- AlsaOutputPtr *self; Data_Get_Struct( rbSelf, AlsaOutputPtr, self );
279
- (*self)->prepare();
280
- } catch ( exception &e ) {
281
- rb_raise( rb_eRuntimeError, "%s", e.what() );
282
- };
283
- return rbSelf;
284
- }
285
-
data/ext/alsaoutput.hh CHANGED
@@ -1,5 +1,5 @@
1
1
  /* HornetsEye - Computer Vision with Ruby
2
- Copyright (C) 2006, 2007, 2008, 2009, 2010 Jan Wedekind
2
+ Copyright (C) 2012 Jan Wedekind
3
3
 
4
4
  This program is free software: you can redistribute it and/or modify
5
5
  it under the terms of the GNU General Public License as published by
@@ -25,9 +25,8 @@
25
25
  class AlsaOutput
26
26
  {
27
27
  public:
28
- AlsaOutput( 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);
28
+ AlsaOutput(const std::string &pcmName = "default:0",
29
+ unsigned int rate = 48000, unsigned int channels = 2) throw (Error);
31
30
  virtual ~AlsaOutput(void);
32
31
  void close(void);
33
32
  void write( SequencePtr sequence ) throw (Error);
@@ -35,28 +34,38 @@ public:
35
34
  void drain(void) throw (Error);
36
35
  unsigned int rate(void);
37
36
  unsigned int channels(void);
38
- int avail(void) throw (Error);
39
37
  int delay(void) throw (Error);
40
- void prepare(void) throw (Error);
38
+ void lock(void);
39
+ void unlock(void);
41
40
  static VALUE cRubyClass;
42
41
  static VALUE registerRubyClass( VALUE rbModule );
43
42
  static void deleteRubyObject( void *ptr );
44
- static VALUE wrapNew( VALUE rbClass, VALUE rbPCMName, VALUE rbRate,
45
- VALUE rbChannels, VALUE rbPeriods, VALUE rbFrames );
43
+ static VALUE wrapNew(VALUE rbClass, VALUE rbPCMName, VALUE rbRate,
44
+ VALUE rbChannels);
46
45
  static VALUE wrapClose( VALUE rbSelf );
47
46
  static VALUE wrapWrite( VALUE rbSelf, VALUE rbSequence );
48
47
  static VALUE wrapDrop( VALUE rbSelf );
49
48
  static VALUE wrapDrain( VALUE rbSelf );
50
49
  static VALUE wrapRate( VALUE rbSelf );
51
50
  static VALUE wrapChannels( VALUE rbSelf );
52
- static VALUE wrapAvail( VALUE rbSelf );
53
51
  static VALUE wrapDelay( VALUE rbSelf );
54
- static VALUE wrapPrepare( VALUE rbSelf );
55
52
  protected:
53
+ int avail(void) throw (Error);
54
+ void writei(short int *data, int count) throw (Error);
55
+ void threadFunc(void);
56
+ static void *staticThreadFunc( void *self );
56
57
  snd_pcm_t *m_pcmHandle;
57
58
  std::string m_pcmName;
58
59
  unsigned int m_rate;
59
60
  unsigned int m_channels;
61
+ snd_pcm_uframes_t m_periodSize;
62
+ bool m_threadInitialised;
63
+ boost::shared_array<short int> m_data;
64
+ int m_start;
65
+ int m_count;
66
+ int m_size;
67
+ pthread_t m_thread;
68
+ pthread_mutex_t m_mutex;
60
69
  };
61
70
 
62
71
  typedef boost::shared_ptr< AlsaOutput > AlsaOutputPtr;
@@ -1,5 +1,5 @@
1
1
  # hornetseye-alsa - Play audio data using libalsa
2
- # Copyright (C) 2010 Jan Wedekind
2
+ # Copyright (C) 2012 Jan Wedekind
3
3
  #
4
4
  # This program is free software: you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -45,14 +45,11 @@ module Hornetseye
45
45
  # @param [String] pcm_name Name of the PCM device
46
46
  # @param [Integer] rate Desired sampling rate.
47
47
  # @param [Integer] channels Number of channels (1=mono, 2=stereo).
48
- # @param [Integer] periods Number of audio frames of the output buffer.
49
- # @param [Integer] frames Size of the audio frames of the output buffer.
50
48
  # @return [AlsaOutput] An object for accessing the speakers.
51
49
  #
52
50
  # @see #rate
53
- def new( pcm_name = 'default', rate = 48000, channels = 2, periods = 8,
54
- frames = 1024 )
55
- orig_new pcm_name, rate, channels, periods, frames
51
+ def new(pcm_name = 'default', rate = 48000, channels = 2)
52
+ orig_new pcm_name, rate, channels
56
53
  end
57
54
 
58
55
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hornetseye-alsa
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
+ - 1
8
9
  - 0
9
- - 0
10
- version: 1.0.0
10
+ version: 1.1.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jan Wedekind
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-11-08 00:00:00 Z
18
+ date: 2012-11-13 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: malloc