Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

AlsaDspSource.cpp

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------------
00002 
00003    Copyright (c) 2004
00004    LS Informationstechnik (LIKE)
00005    University of Erlangen Nuremberg
00006    All rights reserved.
00007 
00008    Tyrell DarkIce
00009 
00010    File     : AlsaDspSource.cpp
00011    Version  : $Revision: 1.4 $
00012    Author   : $Author: darkeye $
00013    Location : $Source: /cvsroot/darkice/darkice/src/AlsaDspSource.cpp,v $
00014    
00015    Copyright notice:
00016 
00017     This program is free software; you can redistribute it and/or
00018     modify it under the terms of the GNU General Public License  
00019     as published by the Free Software Foundation; either version 2
00020     of the License, or (at your option) any later version.
00021    
00022     This program is distributed in the hope that it will be useful,
00023     but WITHOUT ANY WARRANTY; without even the implied warranty of 
00024     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
00025     GNU General Public License for more details.
00026    
00027     You should have received a copy of the GNU General Public License
00028     along with this program; if not, write to the Free Software
00029     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00030 
00031 ------------------------------------------------------------------------------*/
00032 
00033 /* ============================================================ include files */
00034 
00035 #include "AudioSource.h"
00036 
00037 // compile only if configured for ALSA
00038 #ifdef SUPPORT_ALSA_DSP
00039 
00040 #ifdef HAVE_CONFIG_H
00041 #include "config.h"
00042 #endif
00043 
00044 #include "Util.h"
00045 #include "Exception.h"
00046 #include "AlsaDspSource.h"
00047 
00048 
00049 /* ===================================================  local data structures */
00050 
00051 
00052 /* ================================================  local constants & macros */
00053 
00054 /*------------------------------------------------------------------------------
00055  *  File identity
00056  *----------------------------------------------------------------------------*/
00057 static const char fileid[] = "$Id: AlsaDspSource.cpp,v 1.4 2005/04/04 08:36:16 darkeye Exp $";
00058 
00059 
00060 /* ===============================================  local function prototypes */
00061 
00062 
00063 /* =============================================================  module code */
00064 
00065 /*------------------------------------------------------------------------------
00066  *  Tell if source id big endian
00067  *----------------------------------------------------------------------------*/
00068 bool
00069 AlsaDspSource :: isBigEndian ( void ) const                  throw ()
00070 {
00071     return SND_PCM_FORMAT_S16 == SND_PCM_FORMAT_S16_BE;
00072 }
00073 
00074 
00075 /*------------------------------------------------------------------------------
00076  *  Initialize the object
00077  *----------------------------------------------------------------------------*/
00078 void
00079 AlsaDspSource :: init (  const char      * name )    throw ( Exception )
00080 {
00081     pcmName       = Util::strDup( name);
00082     captureHandle = 0;
00083     bufferTime    = 1000000; // Do 1s buffering
00084     running       = false;
00085 }
00086 
00087 
00088 /*------------------------------------------------------------------------------
00089  *  De-initialize the object
00090  *----------------------------------------------------------------------------*/
00091 void
00092 AlsaDspSource :: strip ( void )                      throw ( Exception )
00093 {
00094     if ( isOpen() ) {
00095         close();
00096     }
00097 
00098     delete[] pcmName;
00099 }
00100 
00101 
00102 /*------------------------------------------------------------------------------
00103  *  Open the audio source
00104  *----------------------------------------------------------------------------*/
00105 bool
00106 AlsaDspSource :: open ( void )                       throw ( Exception )
00107 {
00108     unsigned int        u;
00109     snd_pcm_format_t    format;
00110     snd_pcm_hw_params_t *hwParams;
00111 
00112     if ( isOpen() ) {
00113         return false;
00114     }
00115 
00116     switch ( getBitsPerSample() ) {
00117         case 8:
00118             format = SND_PCM_FORMAT_S8;
00119             break;
00120 
00121         case 16:
00122             format = SND_PCM_FORMAT_S16;
00123             break;
00124             
00125         default:
00126             return false;
00127     }
00128 
00129     if (snd_pcm_open(&captureHandle, pcmName, SND_PCM_STREAM_CAPTURE, 0) < 0) {
00130         captureHandle = 0;
00131         return false;
00132     }
00133 
00134     if (snd_pcm_hw_params_malloc(&hwParams) < 0) {
00135         close();
00136         throw Exception( __FILE__, __LINE__, "can't alloc hardware "\
00137                         "parameter structure");
00138     }
00139 
00140     if (snd_pcm_hw_params_any(captureHandle, hwParams) < 0) {
00141         snd_pcm_hw_params_free(hwParams);
00142         close();
00143         throw Exception( __FILE__, __LINE__, "can't initialize hardware "\
00144                         "parameter structure");
00145     }
00146 
00147     if (snd_pcm_hw_params_set_access(captureHandle, hwParams,
00148                                      SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
00149         snd_pcm_hw_params_free(hwParams);
00150         close();
00151         throw Exception( __FILE__, __LINE__, "can't set access type");
00152     }
00153 
00154     if (snd_pcm_hw_params_set_format(captureHandle, hwParams, format) < 0) {
00155         snd_pcm_hw_params_free(hwParams);
00156         close();
00157         throw Exception( __FILE__, __LINE__, "can't set sample format");
00158     }
00159 
00160     u = getSampleRate();
00161     if (snd_pcm_hw_params_set_rate_near(captureHandle, hwParams, &u, 0) < 0) {
00162         snd_pcm_hw_params_free(hwParams);
00163         close();
00164         throw Exception( __FILE__, __LINE__, "can't set sample rate", u);
00165     }
00166 
00167     u = getChannel();
00168     if (snd_pcm_hw_params_set_channels(captureHandle, hwParams, u) < 0) {
00169         snd_pcm_hw_params_free(hwParams);
00170         close();
00171         throw Exception( __FILE__, __LINE__, "can't set channels", u);
00172     }
00173 
00174     u = getBufferTime() / 4;
00175     if (snd_pcm_hw_params_set_period_time_near(captureHandle, hwParams, &u, 0)
00176                                                                           < 0) {
00177         snd_pcm_hw_params_free(hwParams);
00178         close();
00179         throw Exception( __FILE__, __LINE__, "can't set interrupt frequency");
00180     }
00181 
00182     u = getBufferTime();
00183     if (snd_pcm_hw_params_set_buffer_time_near(captureHandle, hwParams, &u, 0)
00184                                                                           < 0) {
00185         snd_pcm_hw_params_free(hwParams);
00186         close();
00187         throw Exception( __FILE__, __LINE__, "can't set buffer size");
00188     }
00189 
00190     if (snd_pcm_hw_params(captureHandle, hwParams) < 0) {
00191         snd_pcm_hw_params_free(hwParams);
00192         close();
00193         throw Exception( __FILE__, __LINE__, "can't set hardware parameters");
00194     }
00195 
00196     snd_pcm_hw_params_free(hwParams);
00197 
00198     if (snd_pcm_prepare(captureHandle) < 0) {
00199         close();
00200         throw Exception( __FILE__, __LINE__, "can't prepare audio interface "\
00201                         "for use");
00202     }
00203 
00204     bytesPerFrame = getChannel() * getBitsPerSample() / 8;
00205 
00206     return true;
00207 }
00208 
00209 
00210 /*------------------------------------------------------------------------------
00211  *  Check wether read() would return anything
00212  *----------------------------------------------------------------------------*/
00213 bool
00214 AlsaDspSource :: canRead ( unsigned int    sec,
00215                            unsigned int    usec )    throw ( Exception )
00216 {
00217     if ( !isOpen() ) {
00218         return false;
00219     }
00220 
00221     if ( !running ) {
00222         snd_pcm_start(captureHandle); 
00223         running = true;
00224     }
00225 
00226     /*
00227      * FIXME How to check for available frames? It
00228      * seems like snd_pcm_wait stops working when
00229      * it comes to ALSA plugins... :-(
00230      *
00231      * int milliDelay = sec * 1000 + usec/1000;
00232      * return snd_pcm_wait(captureHandle, milliDelay)!=0;
00233      */
00234     return true; // bad!!
00235 }
00236 
00237 
00238 /*------------------------------------------------------------------------------
00239  *  Read from the audio source
00240  *----------------------------------------------------------------------------*/
00241 unsigned int
00242 AlsaDspSource :: read (    void          * buf,
00243                            unsigned int    len )     throw ( Exception )
00244 {
00245     snd_pcm_sframes_t ret;
00246 
00247     if ( !isOpen() ) {
00248         return 0;
00249     }
00250 
00251     do {
00252         ret = snd_pcm_readi(captureHandle, buf, len/bytesPerFrame);
00253 
00254         // Check for buffer overrun
00255         if (ret == -EPIPE) {
00256             reportEvent(1, "Buffer overrun!");
00257             snd_pcm_prepare(captureHandle);
00258             ret = -EAGAIN;
00259         }
00260     } while (ret == -EAGAIN);
00261 
00262     if ( ret < 0 ) {
00263         throw Exception(__FILE__, __LINE__, snd_strerror(ret));
00264     }
00265 
00266     running = true;
00267     return ret * bytesPerFrame;
00268 }
00269 
00270 
00271 /*------------------------------------------------------------------------------
00272  *  Close the audio source
00273  *----------------------------------------------------------------------------*/
00274 void
00275 AlsaDspSource :: close ( void )                  throw ( Exception )
00276 {
00277     if ( !isOpen() ) {
00278         return;
00279     }
00280 
00281     snd_pcm_close(captureHandle);
00282 
00283     captureHandle  = 0;
00284     running        = false;
00285 }
00286 
00287 #endif // HAVE_ALSA_LIB
00288 
00289 
00290 /*------------------------------------------------------------------------------
00291  
00292   $Source: /cvsroot/darkice/darkice/src/AlsaDspSource.cpp,v $
00293 
00294   $Log: AlsaDspSource.cpp,v $
00295   Revision 1.4  2005/04/04 08:36:16  darkeye
00296   commited changes to enable Jack support
00297   thanks to Nicholas J. Humfrey, njh@ecs.soton.ac.uk
00298 
00299   Revision 1.3  2005/04/03 05:00:14  jbebel
00300   Fixing code documentation of buffer overruns
00301 
00302   Revision 1.2  2004/02/15 22:36:57  darkeye
00303   proper checking to see if ALSA support is present / needed
00304 
00305   Revision 1.1  2004/02/15 12:06:29  darkeye
00306   added ALSA support, thanks to Christian Forster
00307 
00308 
00309 ------------------------------------------------------------------------------*/
00310 

Generated on Thu Apr 14 13:59:12 2005 for DarkIce by  doxygen 1.4.1