00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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;
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