hornetseye-alsa 1.0.0 → 1.1.0

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