Permalink
Browse files

Added empty AlsaInput implementation

  • Loading branch information...
1 parent 6461c28 commit 0f09f24663c9c97196c2149de4dcd78afbf52f6e @wedesoft committed Nov 14, 2010
Showing with 281 additions and 22 deletions.
  1. +175 −0 ext/alsainput.cc
  2. +55 −0 ext/alsainput.hh
  3. +4 −17 ext/alsaoutput.cc
  4. +1 −4 ext/alsaoutput.hh
  5. +2 −0 ext/init.cc
  6. +42 −0 lib/hornetseye-alsa/alsainput.rb
  7. +1 −1 lib/hornetseye-alsa/alsaoutput.rb
  8. +1 −0 lib/hornetseye_alsa_ext.rb
View
@@ -0,0 +1,175 @@
+/* HornetsEye - Computer Vision with Ruby
+ Copyright (C) 2006, 2007, 2008, 2009, 2010 Jan Wedekind
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#include "alsainput.hh"
+
+using namespace std;
+
+VALUE AlsaInput::cRubyClass = Qnil;
+
+AlsaInput::AlsaInput( const string &pcmName, unsigned int rate,
+ unsigned int channels, int periods,
+ snd_pcm_uframes_t frames ) throw (Error):
+ m_pcmHandle(NULL), m_pcmName( pcmName ), m_rate( rate ), m_channels( channels )
+{
+ try {
+ snd_pcm_hw_params_t *hwParams;
+ snd_pcm_hw_params_alloca( &hwParams );
+ int err = snd_pcm_open( &m_pcmHandle, m_pcmName.c_str(), SND_PCM_STREAM_CAPTURE,
+ SND_PCM_NONBLOCK );
+ ERRORMACRO( err >= 0, Error, , "Error opening PCM device \"" << m_pcmName
+ << "\": " << snd_strerror( err ) );
+ err = snd_pcm_hw_params_any( m_pcmHandle, hwParams );
+ ERRORMACRO( err >= 0, Error, , "Unable to configure the PCM device \""
+ << m_pcmName << "\": " << snd_strerror( err ) );
+ err = snd_pcm_hw_params_set_access( m_pcmHandle, hwParams,
+ SND_PCM_ACCESS_RW_INTERLEAVED );
+ ERRORMACRO( err >= 0, Error, , "Error setting PCM device \""
+ << m_pcmName << "\" to interlaced access: " << snd_strerror( err ) );
+ err = snd_pcm_hw_params_set_format( m_pcmHandle, hwParams,
+ SND_PCM_FORMAT_S16_LE );
+ ERRORMACRO( err >= 0, Error, , "Error setting PCM device \"" << m_pcmName
+ << "\" to 16-bit signed integer format: " << snd_strerror( err ) );
+ err = snd_pcm_hw_params_set_rate_near( m_pcmHandle, hwParams, &m_rate, 0 );
+ ERRORMACRO( err >= 0, Error, , "Error setting sampling rate of PCM device \""
+ << m_pcmName << "\" to " << rate << " Hz: " << snd_strerror( err ) );
+ err = snd_pcm_hw_params_set_channels( m_pcmHandle, hwParams, channels );
+ ERRORMACRO( err >= 0, Error, , "Error setting number of channels of PCM device \""
+ << m_pcmName << "\" to " << channels << ": " << snd_strerror( err ) );
+ err = snd_pcm_hw_params_set_periods( m_pcmHandle, hwParams, periods, 0 );
+ ERRORMACRO( err >= 0, Error, , "Error setting number of periods of PCM device \""
+ << m_pcmName << "\" to " << periods << ": " << snd_strerror( err ) );
+ err = snd_pcm_hw_params_set_buffer_size_near( m_pcmHandle, hwParams, &frames );
+ ERRORMACRO( err >= 0, Error, , "Error setting buffer size of PCM device \""
+ << m_pcmName << "\" to " << frames << " frames: "
+ << snd_strerror( err ) );
+ err = snd_pcm_hw_params( m_pcmHandle, hwParams );
+ ERRORMACRO( err >= 0, Error, , "Error setting parameters of PCM device \""
+ << m_pcmName << "\": " << snd_strerror( err ) );
+ } catch ( Error &e ) {
+ close();
+ throw e;
+ };
+}
+
+AlsaInput::~AlsaInput(void)
+{
+ close();
+}
+
+void AlsaInput::close(void)
+{
+ if ( m_pcmHandle != NULL ) {
+ // drop();
+ snd_pcm_close( m_pcmHandle );
+ m_pcmHandle = NULL;
+ };
+}
+
+SequencePtr AlsaInput::read(void) throw (Error)
+{
+ ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
+ << "\" is not open. Did you call \"close\" before?" );
+#if 0
+ int n = frame->size() / ( 2 * m_channels );
+ int err;
+ while ( ( err = snd_pcm_writei( m_pcmHandle, (short int *)frame->data(),
+ n ) ) < 0 ) {
+ err = snd_pcm_recover( m_pcmHandle, err, 1 );
+ ERRORMACRO( err >= 0, Error, , "Error writing audio frames to PCM device \""
+ << m_pcmName << "\": " << snd_strerror( err ) );
+ };
+ ERRORMACRO( n == err, Error, , "Only managed to write " << err << " of " << n
+ << " frames to PCM device \"" << m_pcmName << "\"" );
+#endif
+ SequencePtr sequence( new Sequence( 1024 ) );
+ return sequence;
+}
+
+unsigned int AlsaInput::rate(void)
+{
+ return m_rate;
+}
+
+unsigned int AlsaInput::channels(void)
+{
+ return m_channels;
+}
+
+VALUE AlsaInput::registerRubyClass( VALUE rbModule )
+{
+ cRubyClass = rb_define_class_under( rbModule, "AlsaInput", rb_cObject );
+ rb_define_singleton_method( cRubyClass, "new",
+ RUBY_METHOD_FUNC( wrapNew ), 5 );
+ rb_define_method( cRubyClass, "close", RUBY_METHOD_FUNC( wrapClose ), 0 );
+ rb_define_method( cRubyClass, "read", RUBY_METHOD_FUNC( wrapRead ), 0 );
+ rb_define_method( cRubyClass, "rate", RUBY_METHOD_FUNC( wrapRate ), 0 );
+ rb_define_method( cRubyClass, "channels", RUBY_METHOD_FUNC( wrapChannels ), 0 );
+}
+
+void AlsaInput::deleteRubyObject( void *ptr )
+{
+ delete (AlsaInputPtr *)ptr;
+}
+
+VALUE AlsaInput::wrapNew( VALUE rbClass, VALUE rbPCMName, VALUE rbRate,
+ VALUE rbChannels, VALUE rbPeriods, VALUE rbFrames )
+{
+ VALUE retVal = Qnil;
+ try {
+ rb_check_type( rbPCMName, T_STRING );
+ AlsaInputPtr ptr( new AlsaInput( StringValuePtr( rbPCMName ),
+ NUM2UINT( rbRate ), NUM2UINT( rbChannels ),
+ NUM2INT( rbPeriods ), NUM2INT( rbFrames ) ) );
+ retVal = Data_Wrap_Struct( rbClass, 0, deleteRubyObject,
+ new AlsaInputPtr( ptr ) );
+ } catch ( exception &e ) {
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
+ };
+ return retVal;
+}
+
+VALUE AlsaInput::wrapClose( VALUE rbSelf )
+{
+ AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
+ (*self)->close();
+ return rbSelf;
+}
+
+VALUE AlsaInput::wrapRead( VALUE rbSelf )
+{
+ VALUE rbRetVal = Qnil;
+ try {
+ AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
+ SequencePtr sequence( (*self)->read() );
+ rbRetVal = sequence->rubyObject();
+ } catch ( exception &e ) {
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
+ };
+ return rbRetVal;
+}
+
+VALUE AlsaInput::wrapRate( VALUE rbSelf )
+{
+ AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
+ return UINT2NUM( (*self)->rate() );
+}
+
+VALUE AlsaInput::wrapChannels( VALUE rbSelf )
+{
+ AlsaInputPtr *self; Data_Get_Struct( rbSelf, AlsaInputPtr, self );
+ return UINT2NUM( (*self)->channels() );
+}
+
View
@@ -0,0 +1,55 @@
+/* HornetsEye - Computer Vision with Ruby
+ Copyright (C) 2006, 2007, 2008, 2009, 2010 Jan Wedekind
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+#ifndef ALSAINPUT_HH
+#define ALSAINPUT_HH
+
+#include <alsa/asoundlib.h>
+#include <string>
+#include "rubyinc.hh"
+#include "error.hh"
+#include "sequence.hh"
+
+class AlsaInput
+{
+public:
+ AlsaInput( const std::string &pcmName = "default:0",
+ unsigned int rate = 48000, unsigned int channels = 2,
+ int periods = 16, snd_pcm_uframes_t frames = 1024 ) throw (Error);
+ virtual ~AlsaInput(void);
+ void close(void);
+ SequencePtr read(void) throw (Error);
+ unsigned int rate(void);
+ unsigned int channels(void);
+ static VALUE cRubyClass;
+ static VALUE registerRubyClass( VALUE rbModule );
+ static void deleteRubyObject( void *ptr );
+ static VALUE wrapNew( VALUE rbClass, VALUE rbPCMName, VALUE rbRate,
+ VALUE rbChannels, VALUE rbPeriods, VALUE rbFrames );
+ static VALUE wrapClose( VALUE rbSelf );
+ static VALUE wrapRead( VALUE rbSelf );
+ static VALUE wrapRate( VALUE rbSelf );
+ static VALUE wrapChannels( VALUE rbSelf );
+protected:
+ snd_pcm_t *m_pcmHandle;
+ std::string m_pcmName;
+ unsigned int m_rate;
+ unsigned int m_channels;
+};
+
+typedef boost::shared_ptr< AlsaInput > AlsaInputPtr;
+
+#endif
+
View
@@ -21,9 +21,8 @@ VALUE AlsaOutput::cRubyClass = Qnil;
AlsaOutput::AlsaOutput( const string &pcmName, unsigned int rate,
unsigned int channels, int periods,
- int frames ) throw (Error):
- m_pcmHandle(NULL), m_pcmName( pcmName ), m_rate( rate ), m_channels( channels ),
- m_frames( frames )
+ snd_pcm_uframes_t frames ) throw (Error):
+ m_pcmHandle(NULL), m_pcmName( pcmName ), m_rate( rate ), m_channels( channels )
{
try {
snd_pcm_hw_params_t *hwParams;
@@ -52,9 +51,9 @@ AlsaOutput::AlsaOutput( const string &pcmName, unsigned int rate,
err = snd_pcm_hw_params_set_periods( m_pcmHandle, hwParams, periods, 0 );
ERRORMACRO( err >= 0, Error, , "Error setting number of periods of PCM device \""
<< m_pcmName << "\" to " << periods << ": " << snd_strerror( err ) );
- err = snd_pcm_hw_params_set_buffer_size_near( m_pcmHandle, hwParams, &m_frames );
+ err = snd_pcm_hw_params_set_buffer_size_near( m_pcmHandle, hwParams, &frames );
ERRORMACRO( err >= 0, Error, , "Error setting buffer size of PCM device \""
- << m_pcmName << "\" to " << m_frames << " frames: "
+ << m_pcmName << "\" to " << frames << " frames: "
<< snd_strerror( err ) );
err = snd_pcm_hw_params( m_pcmHandle, hwParams );
ERRORMACRO( err >= 0, Error, , "Error setting parameters of PCM device \""
@@ -119,11 +118,6 @@ unsigned int AlsaOutput::channels(void)
return m_channels;
}
-unsigned int AlsaOutput::frames(void)
-{
- return m_frames;
-}
-
int AlsaOutput::avail(void) throw (Error)
{
ERRORMACRO( m_pcmHandle != NULL, Error, , "PCM device \"" << m_pcmName
@@ -174,7 +168,6 @@ VALUE AlsaOutput::registerRubyClass( VALUE rbModule )
rb_define_method( cRubyClass, "drain", RUBY_METHOD_FUNC( wrapDrain ), 0 );
rb_define_method( cRubyClass, "rate", RUBY_METHOD_FUNC( wrapRate ), 0 );
rb_define_method( cRubyClass, "channels", RUBY_METHOD_FUNC( wrapChannels ), 0 );
- rb_define_method( cRubyClass, "frames", RUBY_METHOD_FUNC( wrapFrames ), 0 );
rb_define_method( cRubyClass, "avail", RUBY_METHOD_FUNC( wrapAvail ), 0 );
rb_define_method( cRubyClass, "delay", RUBY_METHOD_FUNC( wrapDelay ), 0 );
rb_define_method( cRubyClass, "prepare", RUBY_METHOD_FUNC( wrapPrepare ), 0 );
@@ -255,12 +248,6 @@ VALUE AlsaOutput::wrapChannels( VALUE rbSelf )
return UINT2NUM( (*self)->channels() );
}
-VALUE AlsaOutput::wrapFrames( VALUE rbSelf )
-{
- AlsaOutputPtr *self; Data_Get_Struct( rbSelf, AlsaOutputPtr, self );
- return UINT2NUM( (*self)->frames() );
-}
-
VALUE AlsaOutput::wrapAvail( VALUE rbSelf )
{
VALUE rbRetVal = Qnil;
View
@@ -27,15 +27,14 @@ class AlsaOutput
public:
AlsaOutput( const std::string &pcmName = "default:0",
unsigned int rate = 48000, unsigned int channels = 2,
- int periods = 2, int frames = 1024 ) throw (Error);
+ int periods = 16, snd_pcm_uframes_t frames = 1024 ) throw (Error);
virtual ~AlsaOutput(void);
void close(void);
void write( SequencePtr sequence ) throw (Error);
void drop(void) throw (Error);
void drain(void) throw (Error);
unsigned int rate(void);
unsigned int channels(void);
- unsigned int frames(void);
int avail(void) throw (Error);
int delay(void) throw (Error);
void prepare(void) throw (Error);
@@ -50,7 +49,6 @@ public:
static VALUE wrapDrain( VALUE rbSelf );
static VALUE wrapRate( VALUE rbSelf );
static VALUE wrapChannels( VALUE rbSelf );
- static VALUE wrapFrames( VALUE rbSelf );
static VALUE wrapAvail( VALUE rbSelf );
static VALUE wrapDelay( VALUE rbSelf );
static VALUE wrapPrepare( VALUE rbSelf );
@@ -59,7 +57,6 @@ protected:
std::string m_pcmName;
unsigned int m_rate;
unsigned int m_channels;
- snd_pcm_uframes_t m_frames;
};
typedef boost::shared_ptr< AlsaOutput > AlsaOutputPtr;
View
@@ -14,6 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "alsaoutput.hh"
+#include "alsainput.hh"
#ifdef WIN32
#define DLLEXPORT __declspec(dllexport)
@@ -32,6 +33,7 @@ extern "C" {
rb_require( "multiarray" );
VALUE rbHornetseye = rb_define_module( "Hornetseye" );
AlsaOutput::registerRubyClass( rbHornetseye );
+ AlsaInput::registerRubyClass( rbHornetseye );
rb_require( "hornetseye_alsa_ext.rb" );
}
@@ -0,0 +1,42 @@
+# hornetseye-alsa - Play audio data using libalsa
+# Copyright (C) 2010 Jan Wedekind
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Namespace of Hornetseye computer vision library
+module Hornetseye
+
+ class AlsaInput
+
+ class << self
+
+ alias_method :orig_new, :new
+
+ def new( pcm_name = 'default:0', rate = 48000, channels = 2, periods = 16,
+ frames = 1024 )
+ orig_new pcm_name, rate, channels, periods, frames
+ end
+
+ end
+
+ alias_method :orig_read, :read
+
+ def read
+ orig_read
+ end
+
+ end
+
+end
+
@@ -43,7 +43,7 @@ def write( frame )
raise "Audio frame must have #{channels} channel(s) but had " +
"#{frame.shape.first}"
end
- orig_write Sequence( UBYTE, 2 * frame.size ).new( frame.memory )
+ orig_write Hornetseye::Sequence( UBYTE, 2 * frame.size ).new( frame.memory )
end
end
@@ -14,4 +14,5 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
require 'hornetseye-alsa/alsaoutput'
+require 'hornetseye-alsa/alsainput'

0 comments on commit 0f09f24

Please sign in to comment.