Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

AudioA.cc

Go to the documentation of this file.
00001 /*
00002 
00003     ALSA audio I/O
00004     Copyright (C) 2000-2001 Jussi Laako
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 */
00021 
00022 
00023 #ifdef USE_ALSA05
00024 
00025 
00026 #include <stdio.h>
00027 #include <limits.h>
00028 #include <string.h>
00029 #include <fcntl.h>
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #include <sys/ioctl.h>
00033 #include <sys/asoundlib.h>
00034 
00035 #include "AudioA.hh"
00036 
00037 
00038 static const int iALSAStatusMax = 6;
00039 static const char *cpALSAStatus[] =
00040 {
00041     "Not ready",
00042     "Ready for prepare",
00043     "Ready to go",
00044     "Running",
00045     "Underrun",
00046     "Overrun",
00047     "Paused"
00048 };
00049 static const char *cpALSANullStatus = "Unknown";
00050 
00051 
00052 clAudioA::clAudioA ()
00053 {
00054     iCard = -1;
00055     iDevice = -1;
00056     spSndCtlH = NULL;
00057     spPcmH = NULL;
00058 }
00059 
00060 
00061 clAudioA::~clAudioA ()
00062 {
00063     PcmClose();
00064     CardClose();
00065 }
00066 
00067 
00068 bool clAudioA::CardOpen (int iOCard)
00069 {
00070     if (snd_ctl_open(&spSndCtlH, iOCard) < 0) return false;
00071     if (snd_ctl_hw_info(spSndCtlH, &sHWInfo) < 0) return false;
00072     iCard = iOCard;
00073     return true;
00074 }
00075 
00076 
00077 void clAudioA::CardClose ()
00078 {
00079     if (spSndCtlH != NULL) snd_ctl_close(spSndCtlH);
00080 }
00081 
00082 
00083 int clAudioA::CardGetCount ()
00084 {
00085     return snd_cards();
00086 }
00087 
00088 
00089 const char *clAudioA::CardGetName ()
00090 {
00091     return ((const char *) sHWInfo.name);
00092 }
00093 
00094 
00095 const char *clAudioA::CardGetLongName ()
00096 {
00097     return ((const char *) sHWInfo.longname);
00098 }
00099 
00100 
00101 int clAudioA::CardGetChannelCount ()
00102 {
00103     return sHWInfo.pcmdevs;
00104 }
00105 
00106 
00107 bool clAudioA::PcmOpen (int iODevice, int iOSubDevice, int iOMode)
00108 {
00109     if (iOSubDevice < 0)
00110     {
00111         if (snd_pcm_open(&spPcmH, iCard, iODevice, iOMode) < 0) return false;
00112     }
00113     else
00114     {
00115         if (snd_pcm_open_subdevice(&spPcmH, iCard, iODevice, iOSubDevice, 
00116             iOMode) < 0) return false;
00117     }
00118     memset(&sPCMInfo, 0x00, sizeof(sPCMInfo));
00119     if (snd_pcm_info(spPcmH, &sPCMInfo) < 0) return false;
00120     memset(&sPCMChInfo, 0x00, sizeof(sPCMChInfo));
00121     sPCMChInfo.subdevice = iOSubDevice;
00122     sPCMChInfo.channel = (iOMode == AA_MODE_PLAY) ?
00123         SND_PCM_CHANNEL_PLAYBACK : SND_PCM_CHANNEL_CAPTURE;
00124     #ifndef __QNX__
00125     sPCMChInfo.mode = -1;
00126     #endif
00127     if (snd_pcm_channel_info(spPcmH, &sPCMChInfo) < 0) return false;
00128     iDevice = iODevice;
00129     iSubDevice = iOSubDevice;
00130     iMode = iOMode;
00131     return true;
00132 }
00133 
00134 
00135 void clAudioA::PcmClose ()
00136 {
00137     if (spPcmH != NULL) snd_pcm_close(spPcmH);
00138 }
00139 
00140 
00141 bool clAudioA::PcmSetSetup (int iChannels, int iSampleRate, int iBits, 
00142     int iFragSize, bool bStreamMode)
00143 {
00144     snd_pcm_channel_params_t sChParams;
00145 
00146     bStream = bStreamMode;
00147     PcmFlush();
00148     memset(&sChParams, 0x00, sizeof(sChParams));
00149     sChParams.channel = (iMode == AA_MODE_PLAY) ?
00150         SND_PCM_CHANNEL_PLAYBACK : SND_PCM_CHANNEL_CAPTURE;
00151     sChParams.mode = (bStream) ? 
00152         SND_PCM_MODE_STREAM : SND_PCM_MODE_BLOCK;
00153     sChParams.format.interleave = 1;
00154     switch (iBits)
00155     {
00156         case 8:
00157             sChParams.format.format = SND_PCM_SFMT_U8;
00158             break;
00159         case 16:
00160             sChParams.format.format = SND_PCM_SFMT_S16;
00161             break;
00162         case 24:
00163             sChParams.format.format = SND_PCM_SFMT_S24;
00164             break;
00165         case 32:
00166             sChParams.format.format = SND_PCM_SFMT_S32;
00167             break;
00168         default:
00169             sChParams.format.format = SND_PCM_SFMT_S16;
00170     }
00171     sChParams.format.rate = iSampleRate;
00172     sChParams.format.voices = iChannels;
00173     sChParams.start_mode = (iMode == AA_MODE_PLAY) ? 
00174         SND_PCM_START_FULL : SND_PCM_START_GO;  // SND_PCM_START_DATA
00175     sChParams.stop_mode = SND_PCM_STOP_ROLLOVER;
00176     if (bStream)
00177     {
00178         sChParams.buf.stream.queue_size = iFragSize;
00179         sChParams.buf.stream.fill = (iMode == AA_MODE_PLAY) ? 
00180             SND_PCM_FILL_SILENCE : SND_PCM_FILL_NONE;
00181         sChParams.buf.stream.max_fill = iFragSize;
00182     }
00183     else
00184     {
00185         sChParams.buf.block.frag_size = iFragSize;
00186         sChParams.buf.block.frags_min = AA_FRAG_PLAY_LW;
00187         sChParams.buf.block.frags_max = AA_FRAG_PLAY_HW;
00188     }
00189     if (snd_pcm_channel_params(spPcmH, &sChParams) < 0) return false;
00190     memset(&sPCMSetup, 0x00, sizeof(sPCMSetup));
00191     sPCMSetup.channel = (iMode == AA_MODE_PLAY) ?
00192         SND_PCM_CHANNEL_PLAYBACK : SND_PCM_CHANNEL_CAPTURE;
00193     sPCMSetup.mode = (bStream) ?
00194         SND_PCM_MODE_STREAM : SND_PCM_MODE_BLOCK;
00195     if (snd_pcm_channel_setup(spPcmH, &sPCMSetup) < 0) return false;
00196     return true;
00197 }
00198 
00199 
00200 int clAudioA::PcmGetChannels ()
00201 {
00202     return sPCMSetup.format.voices;
00203 }
00204 
00205 
00206 int clAudioA::PcmGetSampleRate ()
00207 {
00208     return sPCMSetup.format.rate;
00209 }
00210 
00211 
00212 int clAudioA::PcmGetBits ()
00213 {
00214     switch (sPCMSetup.format.format)
00215     {
00216         case SND_PCM_SFMT_U8:
00217             return 8;
00218         case SND_PCM_SFMT_S16:
00219             return 16;
00220         case SND_PCM_SFMT_S24:
00221             return 24;
00222         case SND_PCM_SFMT_S32:
00223             return 32;
00224         default:
00225             return -1;
00226     }
00227 }
00228 
00229 
00230 int clAudioA::PcmGetFragmentSize ()
00231 {
00232     return sPCMSetup.buf.block.frag_size;
00233 }
00234 
00235 
00236 const char *clAudioA::PcmGetFormatName ()
00237 {
00238     return snd_pcm_get_format_name(sPCMSetup.format.format);
00239 }
00240 
00241 
00242 int clAudioA::PcmGetStatus ()
00243 {
00244     snd_pcm_channel_status_t sChStatus;
00245 
00246     if (!PcmGetChannelStatus(&sChStatus)) return -1;
00247     return sChStatus.status;
00248 }
00249 
00250 
00251 const char *clAudioA::PcmGetStatusStr (int iStatusCode)
00252 {
00253     if (iStatusCode >= 0 && iStatusCode <= iALSAStatusMax)
00254         return cpALSAStatus[iStatusCode];
00255     else
00256         return cpALSANullStatus;
00257 }
00258 
00259 
00260 const char *clAudioA::PcmGetName ()
00261 {
00262     return ((const char *) sPCMInfo.name);
00263 }
00264 
00265 
00266 const snd_pcm_channel_info_t *clAudioA::PcmGetChannelInfo ()
00267 {
00268     return &sPCMChInfo;
00269 }
00270 
00271 
00272 bool clAudioA::PcmGetChannelStatus (snd_pcm_channel_status_t *spChStatus)
00273 {
00274     memset(spChStatus, 0x00, sizeof(snd_pcm_channel_status_t));
00275     spChStatus->channel = (iMode == AA_MODE_PLAY) ?
00276         SND_PCM_CHANNEL_PLAYBACK : SND_PCM_CHANNEL_CAPTURE;
00277     spChStatus->mode = (bStream) ?
00278         SND_PCM_MODE_STREAM : SND_PCM_MODE_BLOCK;
00279     if (snd_pcm_channel_status(spPcmH, spChStatus) < 0) return false;
00280     return true;
00281 }
00282 
00283 
00284 int clAudioA::PcmGetBufUsed ()
00285 {
00286     snd_pcm_channel_status_t sChStatus;
00287 
00288     if (!PcmGetChannelStatus(&sChStatus)) return -1;
00289     return sChStatus.count;
00290 }
00291 
00292 
00293 int clAudioA::PcmGetBufFree ()
00294 {
00295     snd_pcm_channel_status_t sChStatus;
00296 
00297     if (!PcmGetChannelStatus(&sChStatus)) return -1;
00298     return sChStatus.free;
00299 }
00300 
00301 
00302 bool clAudioA::PcmPrepare ()
00303 {
00304     if (iMode == AA_MODE_PLAY)
00305     {
00306         if (snd_pcm_playback_prepare(spPcmH) < 0) return false;
00307     }
00308     else
00309     {
00310         if (snd_pcm_capture_prepare(spPcmH) < 0) return false;
00311     }
00312     return true;
00313 }
00314 
00315 
00316 bool clAudioA::PcmGo ()
00317 {
00318     if (iMode == AA_MODE_PLAY)
00319     {
00320         if (snd_pcm_playback_go(spPcmH) < 0) return false;
00321     }
00322     else
00323     {
00324         if (snd_pcm_capture_go(spPcmH) < 0) return false;
00325     }
00326     return true;
00327 }
00328 
00329 
00330 bool clAudioA::PcmDrain ()
00331 {
00332     if (iMode == AA_MODE_PLAY)
00333     {
00334         if (snd_pcm_playback_drain(spPcmH) < 0) return false;
00335     }
00336     return true;
00337 }
00338 
00339 
00340 bool clAudioA::PcmFlush ()
00341 {
00342     if (iMode == AA_MODE_PLAY)
00343     {
00344         if (snd_pcm_playback_flush(spPcmH) < 0) return false;
00345     }
00346     else
00347     {
00348         if (snd_pcm_capture_flush(spPcmH) < 0) return false;
00349     }
00350     return true;
00351 }
00352 
00353 
00354 ssize_t clAudioA::PcmGetTransferSize ()
00355 {
00356     if (iMode == AA_MODE_PLAY)
00357         return snd_pcm_transfer_size(spPcmH, SND_PCM_CHANNEL_PLAYBACK);
00358     else
00359         return snd_pcm_transfer_size(spPcmH, SND_PCM_CHANNEL_CAPTURE);
00360 }
00361 
00362 
00363 ssize_t clAudioA::PcmRead (void *vpBuffer, size_t iBufSize)
00364 {
00365     return snd_pcm_read(spPcmH, vpBuffer, iBufSize);
00366 }
00367 
00368 
00369 ssize_t clAudioA::PcmWrite (const void *vpBuffer, size_t iBufSize)
00370 {
00371     return snd_pcm_write(spPcmH, vpBuffer, iBufSize);
00372 }
00373 
00374 #endif  // USE_ALSA05

Generated on Sun Oct 26 19:11:18 2003 for HASAS by doxygen 1.3.3