Changeset 7454 in vbox
- Timestamp:
- Mar 14, 2008 10:00:39 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/solaudio.c
r7333 r7454 24 24 #include <fcntl.h> 25 25 #include <sys/audio.h> 26 #include <sys/fcntl.h>27 26 #include <sys/stat.h> 28 27 #include <sys/time.h> … … 30 29 #define LOG_GROUP LOG_GROUP_DEV_AUDIO 31 30 #include <VBox/log.h> 31 #include <iprt/env.h> 32 32 33 33 #include "Builtins.h" … … 39 39 #include "audio_int.h" 40 40 41 42 41 /******************************************************************************* 43 42 * Structures and Typedefs * 44 43 *******************************************************************************/ 45 44 typedef struct solaudioVoiceOut { 46 HWVoiceOut hw;45 HWVoiceOut Hw; 47 46 int AudioDev; 48 47 int AudioCtl; … … 57 56 struct 58 57 { 59 int buffer_size; 60 int nbuffers; 58 int cbBuffer; 61 59 } conf = 62 60 { 63 INIT_FIELD (buffer_size =) 8192, 64 INIT_FIELD (nbuffers =) 4, 61 INIT_FIELD (cbBuffer =) 8912, 65 62 }; 66 63 … … 70 67 va_list ap; 71 68 72 va_start 73 AUD_vlog 74 va_end 75 76 AUD_log (AUDIO_CAP, "Reason: %s\n", strerror(err));69 va_start(ap, fmt); 70 AUD_vlog(AUDIO_CAP, fmt, ap); 71 va_end(ap); 72 73 AUD_log(AUDIO_CAP, "Reason: %s\n", strerror(err)); 77 74 } 78 75 … … 111 108 112 109 case AUDIO_PRECISION_16: 113 return AUD_FMT_U16; 110 { 111 if (encoding == AUDIO_ENCODING_LINEAR) 112 return AUD_FMT_S16; 113 else 114 return AUD_FMT_U16; 115 break; 116 } 114 117 115 118 default: … … 120 123 121 124 125 static char *solaudio_getdevice () 126 { 127 /* This is for multiple audio devices where env. var determines current one, 128 * otherwise else we fallback to default. 129 */ 130 char *pszAudioDev = RTEnvGet("AUDIODEV"); 131 if (pszAudioDev) 132 return RTStrDup(pszAudioDev); 133 134 return RTStrDup("/dev/audio"); 135 } 136 137 122 138 static int solaudio_open (int in, audio_info_t *info, int *pfd, int *pctl_fd) 123 139 { 124 int fd; 125 int ctl_fd; 126 struct stat st; 127 const char *deviceName = "/dev/audio"; 128 const char *ctlDeviceName = "/dev/audioctl"; 129 audio_info_t audInfo; 130 131 /* @todo Use AUDIO_GETDEV instead of hardcoding /dev/audio */ 132 if (stat(deviceName, &st) < 0) 133 { 134 LogRel(("solaudio: failed to stat %s\n", deviceName)); 135 return -1; 136 } 137 138 if (!S_ISCHR(st.st_mode)) 139 { 140 LogRel(("solaudio: invalid mode for %s\n", deviceName)); 141 return -1; 142 } 143 144 fd = open(deviceName, O_WRONLY | O_NONBLOCK); 145 if (fd < 0) 146 { 147 LogRel(("solaudio: failed to open %s\n", deviceName)); 148 return -1; 149 } 150 151 ctl_fd = open(ctlDeviceName, O_WRONLY | O_NONBLOCK); 152 if (ctl_fd < 0) 153 { 154 LogRel(("solaudio: failed to open %s\n", ctlDeviceName)); 155 close(fd); 156 return -1; 157 } 158 159 AUDIO_INITINFO(&audInfo); 160 if (ioctl(fd, AUDIO_GETINFO, &audInfo) < 0) 140 int AudioDev; 141 int AudioCtl; 142 struct stat FileStat; 143 const char *pszAudioDev = NULL; 144 const char *pszAudioCtl = "/dev/audioctl"; 145 audio_info_t AudioInfo; 146 147 pszAudioDev = solaudio_getdevice(); 148 if (!pszAudioDev) 149 { 150 LogRel(("solaudio: solaudio_getdevice() failed to return a valid device.\n")); 151 goto err; 152 } 153 154 if (stat(pszAudioDev, &FileStat) < 0) 155 { 156 LogRel(("solaudio: failed to stat %s\n", pszAudioDev)); 157 goto err; 158 } 159 160 if (!S_ISCHR(FileStat.st_mode)) 161 { 162 LogRel(("solaudio: invalid mode for %s\n", pszAudioDev)); 163 goto err; 164 } 165 166 AudioDev = open(pszAudioDev, O_WRONLY | O_NONBLOCK); 167 if (AudioDev < 0) 168 { 169 LogRel(("solaudio: failed to open %s\n", pszAudioDev)); 170 goto err; 171 } 172 173 AudioCtl = open(pszAudioCtl, O_WRONLY | O_NONBLOCK); 174 if (AudioCtl < 0) 175 { 176 LogRel(("solaudio: failed to open %s\n", pszAudioCtl)); 177 close(AudioDev); 178 goto err; 179 } 180 181 AUDIO_INITINFO(&AudioInfo); 182 if (ioctl(AudioDev, AUDIO_GETINFO, &AudioInfo) < 0) 161 183 { 162 184 LogRel(("solaudio: AUDIO_GETINFO failed\n")); 163 close(fd); 164 return -1; 165 } 166 audInfo.play.sample_rate = info->play.sample_rate; 167 audInfo.play.channels = info->play.channels; 168 audInfo.play.precision = info->play.precision; 169 audInfo.play.encoding = info->play.encoding; 170 audInfo.play.buffer_size = info->play.buffer_size; 171 audInfo.play.gain = AUDIO_MID_GAIN; 172 if (ioctl(fd, AUDIO_SETINFO, &audInfo) < 0) 185 close(AudioDev); 186 close(AudioCtl); 187 goto err; 188 } 189 AudioInfo.play.sample_rate = info->play.sample_rate; 190 AudioInfo.play.channels = info->play.channels; 191 AudioInfo.play.precision = info->play.precision; 192 AudioInfo.play.encoding = info->play.encoding; 193 AudioInfo.play.buffer_size = info->play.buffer_size; 194 AudioInfo.play.gain = AUDIO_MAX_GAIN; 195 AudioInfo.play.balance = AUDIO_MID_BALANCE; 196 if (ioctl(AudioDev, AUDIO_SETINFO, &AudioInfo) < 0) 173 197 { 174 198 LogRel(("solaudio: AUDIO_SETINFO failed\n")); 175 close(fd); 176 return -1; 177 } 178 LogFlow(("solaudio: system buffer_size=%d\n", audInfo.play.buffer_size)); 179 *pfd = fd; 180 *pctl_fd = ctl_fd; 199 close(AudioDev); 200 close(AudioCtl); 201 goto err; 202 } 203 LogFlow(("solaudio: buffer_size=%d\n", AudioInfo.play.buffer_size)); 204 *pfd = AudioDev; 205 *pctl_fd = AudioCtl; 181 206 return 0; 207 208 err: 209 RTStrFree(pszAudioDev); 210 return -1; 182 211 } 183 212 … … 185 214 static int solaudio_init_out (HWVoiceOut *hw, audsettings_t *as) 186 215 { 187 solaudioVoiceOut * sol = (solaudioVoiceOut *)hw;188 audio_info_t audioInfo;189 audsettings_t obt_as;190 int fd= -1;191 int ctl_fd= -1;192 193 AUDIO_INITINFO(& audioInfo);194 audioInfo.play.sample_rate = as->freq;195 audioInfo.play.channels = as->nchannels;196 audioInfo.play.precision = aud_to_solfmt(as->fmt);197 audioInfo.play.buffer_size = conf.buffer_size;216 solaudioVoiceOut *pSol = (solaudioVoiceOut *)hw; 217 audio_info_t AudioInfo; 218 audsettings_t ObtAudioInfo; 219 int AudioDev = -1; 220 int AudioCtl = -1; 221 222 AUDIO_INITINFO(&AudioInfo); 223 AudioInfo.play.sample_rate = as->freq; 224 AudioInfo.play.channels = as->nchannels; 225 AudioInfo.play.precision = aud_to_solfmt(as->fmt); 226 AudioInfo.play.buffer_size = conf.cbBuffer; 198 227 if (as->fmt == AUD_FMT_U8) 199 audioInfo.play.encoding = AUDIO_ENCODING_LINEAR8;228 AudioInfo.play.encoding = AUDIO_ENCODING_LINEAR8; 200 229 else 201 audioInfo.play.encoding = AUDIO_ENCODING_LINEAR;202 203 if (solaudio_open(0, & audioInfo, &fd, &ctl_fd))230 AudioInfo.play.encoding = AUDIO_ENCODING_LINEAR; 231 232 if (solaudio_open(0, &AudioInfo, &AudioDev, &AudioCtl)) 204 233 { 205 234 LogRel(("solaudio: solaudio_open failed\n")); … … 207 236 } 208 237 209 sol->AudioDev = fd;210 sol->AudioCtl = ctl_fd;211 obt_as.freq = audioInfo.play.sample_rate;212 obt_as.nchannels = audioInfo.play.channels;213 obt_as.fmt = sol_to_audfmt(audioInfo.play.precision, audioInfo.play.encoding);214 obt_as.endianness = as->endianness;215 216 audio_pcm_init_info (&hw->info, &obt_as);217 sol->cBuffersPlayed = audioInfo.play.eof;218 219 hw->samples = audioInfo.play.buffer_size >> hw->info.shift;220 sol->pPCMBuf = RTMemAllocZ(audioInfo.play.buffer_size);221 if (! sol->pPCMBuf)238 pSol->AudioDev = AudioDev; 239 pSol->AudioCtl = AudioCtl; 240 ObtAudioInfo.freq = AudioInfo.play.sample_rate; 241 ObtAudioInfo.nchannels = AudioInfo.play.channels; 242 ObtAudioInfo.fmt = sol_to_audfmt(AudioInfo.play.precision, AudioInfo.play.encoding); 243 ObtAudioInfo.endianness = as->endianness; 244 245 audio_pcm_init_info(&hw->info, &ObtAudioInfo); 246 pSol->cBuffersPlayed = AudioInfo.play.eof; 247 248 hw->samples = AudioInfo.play.buffer_size >> hw->info.shift; 249 pSol->pPCMBuf = RTMemAllocZ(AudioInfo.play.buffer_size); 250 if (!pSol->pPCMBuf) 222 251 { 223 252 LogRel(("solaudio: failed to alloc %d %d bytes to pPCMBuf\n", hw->samples << hw->info.shift, hw->samples)); 224 253 return -1; 225 254 } 226 LogFlow(("solaudio: hw->samples=%d play.buffer_size=%d\n", hw->samples, audioInfo.play.buffer_size));255 LogFlow(("solaudio: hw->samples=%d play.buffer_size=%d\n", hw->samples, AudioInfo.play.buffer_size)); 227 256 return 0; 228 257 } 229 258 230 259 231 static void solaudio_stop (solaudioVoiceOut *sol vw)260 static void solaudio_stop (solaudioVoiceOut *sol) 232 261 { 233 262 LogFlow(("solaudio: stop\n")); 234 if (sol vw->AudioDev < 0 || solvw->AudioCtl < 0)263 if (sol->AudioDev < 0 || sol->AudioCtl < 0) 235 264 { 236 265 Log(("solaudio: invalid file descriptors\n")); … … 238 267 } 239 268 240 if (ioctl(sol vw->AudioCtl, I_SETSIG, 0) < 0)269 if (ioctl(sol->AudioCtl, I_SETSIG, 0) < 0) 241 270 { 242 271 LogRel(("solaudio: failed to stop signalling\n")); … … 244 273 } 245 274 246 if (ioctl(sol vw->AudioDev, I_FLUSH, FLUSHW) < 0)275 if (ioctl(sol->AudioDev, I_FLUSH, FLUSHW) < 0) 247 276 { 248 277 Log(("solaudio: failed to drop unplayed buffers\n")); … … 250 279 } 251 280 252 close(sol vw->AudioDev);253 sol vw->AudioDev = -1;254 close(sol vw->AudioCtl);255 sol vw->AudioCtl = -1;256 sol vw->cBuffersPlayed = 0;257 if (sol vw->pPCMBuf)258 { 259 RTMemFree(sol vw->pPCMBuf);260 sol vw->pPCMBuf = NULL;281 close(sol->AudioDev); 282 sol->AudioDev = -1; 283 close(sol->AudioCtl); 284 sol->AudioCtl = -1; 285 sol->cBuffersPlayed = 0; 286 if (sol->pPCMBuf) 287 { 288 RTMemFree(sol->pPCMBuf); 289 sol->pPCMBuf = NULL; 261 290 } 262 291 } … … 271 300 272 301 273 static int solaudio_availbuf (solaudioVoiceOut *sol vw)274 { 275 audio_info_t audioInfo;276 int buffers= 0;277 278 AUDIO_INITINFO(& audioInfo);279 if (ioctl(sol vw->AudioDev, AUDIO_GETINFO, &audioInfo) < 0)302 static int solaudio_availbuf (solaudioVoiceOut *sol) 303 { 304 audio_info_t AudioInfo; 305 int cbBuffer = 0; 306 307 AUDIO_INITINFO(&AudioInfo); 308 if (ioctl(sol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0) 280 309 { 281 310 Log(("solaudio: AUDIO_GETINFO ioctl failed\n")); … … 283 312 } 284 313 285 buffers = audioInfo.play.buffer_size * (2 + audioInfo.play.eof - solvw->cBuffersPlayed); 286 287 LogFlow(("avail: eof=%d samples=%d bufsize=%d bufplayed=%d avail=%d\n", audioInfo.play.eof, audioInfo.play.samples, 288 audioInfo.play.buffer_size, solvw->cBuffersPlayed, buffers)); 289 return buffers; 290 } 291 314 cbBuffer = AudioInfo.play.buffer_size * (2 + AudioInfo.play.eof - sol->cBuffersPlayed); 315 316 LogFlow(("avail: eof=%d samples=%d bufsize=%d bufplayed=%d avail=%d\n", AudioInfo.play.eof, AudioInfo.play.samples, 317 AudioInfo.play.buffer_size, sol->cBuffersPlayed, cbBuffer)); 318 return cbBuffer; 319 } 320 321 #if 0 292 322 static void solaudio_yield (solaudioVoiceOut *pSol) 293 323 { 294 324 audio_info_t AudioInfo; 295 325 timespec_t WaitTimeSpec; 296 if (ioctl 326 if (ioctl(pSol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0) 297 327 return; 298 328 299 329 WaitTimeSpec.tv_sec = 0; 300 WaitTimeSpec.tv_nsec = 1000000 0;330 WaitTimeSpec.tv_nsec = 1000000; 301 331 302 332 while (AudioInfo.play.eof < pSol->cBuffersPlayed - 2) … … 307 337 } 308 338 } 309 339 #endif 310 340 311 341 static int solaudio_run_out (HWVoiceOut *hw) … … 317 347 st_sample_t *psSrc; 318 348 319 csLive = audio_pcm_hw_get_live_out 349 csLive = audio_pcm_hw_get_live_out(hw); 320 350 if (!csLive) 321 351 return 0; 322 352 323 for (;;) 324 { 325 cbAvail = solaudio_availbuf (pSol); 326 if (cbAvail > 0) 327 break; 328 solaudio_yield(pSol); 329 } 353 cbAvail = solaudio_availbuf(pSol); 354 if (cbAvail <= 0) 355 return 0; 330 356 331 357 csAvail = cbAvail >> hw->info.shift; /* bytes => samples */ 332 csDecr = audio_MIN 358 csDecr = audio_MIN(csLive, csAvail); 333 359 csSamples = csDecr; 334 360 … … 336 362 { 337 363 /* split request at the end of our samples buffer */ 338 csToWrite = audio_MIN 364 csToWrite = audio_MIN(csSamples, hw->samples - hw->rpos); 339 365 cbToWrite = csToWrite << hw->info.shift; 340 366 psSrc = hw->mix_buf + hw->rpos; 341 pu8Dst = advance 342 343 hw->clip 344 345 cbWritten = write 367 pu8Dst = advance(pSol->pPCMBuf, hw->rpos << hw->info.shift); 368 369 hw->clip(pu8Dst, psSrc, csToWrite); 370 371 cbWritten = write(pSol->AudioDev, pu8Dst, cbToWrite); 346 372 if (cbWritten < 0) 347 373 break; … … 359 385 static int solaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) 360 386 { 361 solaudioVoiceOut * sol = (solaudioVoiceOut *) hw;387 solaudioVoiceOut *pSol = (solaudioVoiceOut *) hw; 362 388 switch (cmd) 363 389 { … … 365 391 { 366 392 /* reset the eof marker and samples markers */ 367 audio_info_t audioInfo;368 AUDIO_INITINFO(& audioInfo);369 ioctl( sol->AudioDev, AUDIO_GETINFO, &audioInfo);370 audioInfo.play.eof = 0;371 audioInfo.play.samples = 0;372 ioctl( sol->AudioDev, AUDIO_SETINFO, &audioInfo);373 374 sol->cBuffersPlayed = 0; 375 audio_pcm_info_clear_buf (&hw->info, sol->pPCMBuf, hw->samples);393 audio_info_t AudioInfo; 394 AUDIO_INITINFO(&AudioInfo); 395 ioctl(pSol->AudioDev, AUDIO_GETINFO, &AudioInfo); 396 AudioInfo.play.eof = 0; 397 AudioInfo.play.samples = 0; 398 ioctl(pSol->AudioDev, AUDIO_SETINFO, &AudioInfo); 399 pSol->cBuffersPlayed = 0; 400 401 audio_pcm_info_clear_buf(&hw->info, pSol->pPCMBuf, hw->samples); 376 402 LogFlow(("solaudio: voice_enable\n")); 377 403 break; … … 381 407 { 382 408 LogFlow(("solaudio: voice_disable\n")); 383 solaudio_stop( sol);409 solaudio_stop(pSol); 384 410 break; 385 411 } … … 422 448 423 449 static struct audio_option solaudio_options[] = { 424 {"BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size, 425 "Size of the buffer in frames", NULL, 0}, 426 {"BUFFER_COUNT", AUD_OPT_INT, &conf.nbuffers, 427 "Number of buffers", NULL, 0}, 450 {"BUFFER_SIZE", AUD_OPT_INT, &conf.cbBuffer, 451 "Size of the buffer in bytes", NULL, 0}, 428 452 {NULL, 0, NULL, NULL, NULL, 0} 429 453 };
Note:
See TracChangeset
for help on using the changeset viewer.