Changeset 7333 in vbox
- Timestamp:
- Mar 6, 2008 4:29:34 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/solaudio.c
r6000 r7333 26 26 #include <sys/fcntl.h> 27 27 #include <sys/stat.h> 28 #include <sys/ mman.h>28 #include <sys/time.h> 29 29 30 30 #define LOG_GROUP LOG_GROUP_DEV_AUDIO … … 45 45 typedef struct solaudioVoiceOut { 46 46 HWVoiceOut hw; 47 int fd;48 int ctl_fd;49 int buffers_played;50 void *pcm_buf;47 int AudioDev; 48 int AudioCtl; 49 int cBuffersPlayed; 50 void *pPCMBuf; 51 51 } solaudioVoiceOut; 52 52 … … 61 61 } conf = 62 62 { 63 INIT_FIELD (buffer_size =) 4096,63 INIT_FIELD (buffer_size =) 8192, 64 64 INIT_FIELD (nbuffers =) 4, 65 65 }; 66 66 67 67 68 static void GCC_FMT_ATTR (2, 3) solaudio_logerr (int err, const char *fmt, ...) … … 118 119 } 119 120 121 120 122 static int solaudio_open (int in, audio_info_t *info, int *pfd, int *pctl_fd) 121 123 { … … 127 129 audio_info_t audInfo; 128 130 129 /* @todo add Log for failures.Use AUDIO_GETDEV instead of hardcoding /dev/audio */131 /* @todo Use AUDIO_GETDEV instead of hardcoding /dev/audio */ 130 132 if (stat(deviceName, &st) < 0) 131 return -1; 133 { 134 LogRel(("solaudio: failed to stat %s\n", deviceName)); 135 return -1; 136 } 132 137 133 138 if (!S_ISCHR(st.st_mode)) 134 return -1; 139 { 140 LogRel(("solaudio: invalid mode for %s\n", deviceName)); 141 return -1; 142 } 135 143 136 144 fd = open(deviceName, O_WRONLY | O_NONBLOCK); 137 145 if (fd < 0) 138 return -1; 146 { 147 LogRel(("solaudio: failed to open %s\n", deviceName)); 148 return -1; 149 } 139 150 140 151 ctl_fd = open(ctlDeviceName, O_WRONLY | O_NONBLOCK); 141 152 if (ctl_fd < 0) 142 153 { 154 LogRel(("solaudio: failed to open %s\n", ctlDeviceName)); 143 155 close(fd); 144 156 return -1; … … 190 202 191 203 if (solaudio_open(0, &audioInfo, &fd, &ctl_fd)) 192 return -1; 193 194 sol->fd = fd; 195 sol->ctl_fd = ctl_fd; 204 { 205 LogRel(("solaudio: solaudio_open failed\n")); 206 return -1; 207 } 208 209 sol->AudioDev = fd; 210 sol->AudioCtl = ctl_fd; 196 211 obt_as.freq = audioInfo.play.sample_rate; 197 212 obt_as.nchannels = audioInfo.play.channels; … … 200 215 201 216 audio_pcm_init_info (&hw->info, &obt_as); 202 sol-> buffers_played = audioInfo.play.eof;203 204 hw->samples = audioInfo.play.buffer_size / 2;205 sol->p cm_buf = RTMemAllocZ(hw->samples << hw->info.shift);206 if (!sol->p cm_buf)207 { 208 LogRel(("solaudio: failed to alloc %d %d bytes to p cm_buf\n", hw->samples << hw->info.shift, hw->samples));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) 222 { 223 LogRel(("solaudio: failed to alloc %d %d bytes to pPCMBuf\n", hw->samples << hw->info.shift, hw->samples)); 209 224 return -1; 210 225 } … … 213 228 } 214 229 230 215 231 static void solaudio_stop (solaudioVoiceOut *solvw) 216 232 { 217 233 LogFlow(("solaudio: stop\n")); 218 if (solvw->fd < 0 || solvw->ctl_fd < 0) 234 if (solvw->AudioDev < 0 || solvw->AudioCtl < 0) 235 { 236 Log(("solaudio: invalid file descriptors\n")); 219 237 return; 220 221 if (ioctl(solvw->ctl_fd, I_SETSIG, 0) < 0) 238 } 239 240 if (ioctl(solvw->AudioCtl, I_SETSIG, 0) < 0) 241 { 242 LogRel(("solaudio: failed to stop signalling\n")); 222 243 return; 223 224 if (ioctl(solvw->fd, I_FLUSH, FLUSHW) < 0) 244 } 245 246 if (ioctl(solvw->AudioDev, I_FLUSH, FLUSHW) < 0) 247 { 248 Log(("solaudio: failed to drop unplayed buffers\n")); 225 249 return; 226 227 close(solvw->fd); 228 solvw->fd = -1; 229 close(solvw->ctl_fd); 230 solvw->ctl_fd = -1; 231 solvw->buffers_played = 0; 232 if (solvw->pcm_buf) 233 { 234 RTMemFree(solvw->pcm_buf); 235 solvw->pcm_buf = NULL; 236 } 237 } 250 } 251 252 close(solvw->AudioDev); 253 solvw->AudioDev = -1; 254 close(solvw->AudioCtl); 255 solvw->AudioCtl = -1; 256 solvw->cBuffersPlayed = 0; 257 if (solvw->pPCMBuf) 258 { 259 RTMemFree(solvw->pPCMBuf); 260 solvw->pPCMBuf = NULL; 261 } 262 } 263 238 264 239 265 static void solaudio_fini_out (HWVoiceOut *hw) … … 241 267 solaudioVoiceOut *sol = (solaudioVoiceOut *) hw; 242 268 solaudio_stop (sol); 243 LogFlow(("solaudio: fini_out done .\n"));269 LogFlow(("solaudio: fini_out done\n")); 244 270 } 245 271 … … 248 274 { 249 275 audio_info_t audioInfo; 250 int buffers ;276 int buffers = 0; 251 277 252 278 AUDIO_INITINFO(&audioInfo); 253 if (ioctl(solvw->fd, AUDIO_GETINFO, &audioInfo) < 0) 254 return -1; 255 256 buffers = audioInfo.play.buffer_size * (2 + audioInfo.play.eof - solvw->buffers_played); 279 if (ioctl(solvw->AudioDev, AUDIO_GETINFO, &audioInfo) < 0) 280 { 281 Log(("solaudio: AUDIO_GETINFO ioctl failed\n")); 282 return -1; 283 } 284 285 buffers = audioInfo.play.buffer_size * (2 + audioInfo.play.eof - solvw->cBuffersPlayed); 257 286 258 287 LogFlow(("avail: eof=%d samples=%d bufsize=%d bufplayed=%d avail=%d\n", audioInfo.play.eof, audioInfo.play.samples, 259 audioInfo.play.buffer_size, solvw-> buffers_played, buffers));288 audioInfo.play.buffer_size, solvw->cBuffersPlayed, buffers)); 260 289 return buffers; 261 290 } 262 291 292 static void solaudio_yield (solaudioVoiceOut *pSol) 293 { 294 audio_info_t AudioInfo; 295 timespec_t WaitTimeSpec; 296 if (ioctl (pSol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0) 297 return; 298 299 WaitTimeSpec.tv_sec = 0; 300 WaitTimeSpec.tv_nsec = 10000000; 301 302 while (AudioInfo.play.eof < pSol->cBuffersPlayed - 2) 303 { 304 nanosleep(&WaitTimeSpec, NULL); 305 if (ioctl(pSol->AudioDev, AUDIO_GETINFO, &AudioInfo) < 0) 306 break; 307 } 308 } 309 310 263 311 static int solaudio_run_out (HWVoiceOut *hw) 264 312 { 265 solaudioVoiceOut *sol = (solaudioVoiceOut *) hw; 266 int live, samples, rpos, decr, avail; 267 uint16_t *dst = NULL; 268 st_sample_t *src; 269 270 live = audio_pcm_hw_get_live_out (hw); 271 if (!live) 313 solaudioVoiceOut *pSol = (solaudioVoiceOut *) hw; 314 int csLive, csDecr, csSamples, csToWrite, csAvail; 315 size_t cbAvail, cbToWrite, cbWritten; 316 uint8_t *pu8Dst; 317 st_sample_t *psSrc; 318 319 csLive = audio_pcm_hw_get_live_out (hw); 320 if (!csLive) 272 321 return 0; 273 322 274 avail = solaudio_availbuf(sol); 275 if (avail <= 0) 276 return 0; 277 278 decr = audio_MIN(live, avail); 279 samples = decr; 280 rpos = hw->rpos; 281 LogFlow(("solaudio: run_out: samples=%d live=%d avail=%d\n", samples, live, avail)); 282 while (samples) 283 { 284 int left_till_end_samples = hw->samples - rpos; 285 int convert_samples = audio_MIN (samples, left_till_end_samples); 286 int written = 0; 287 288 src = hw->mix_buf + rpos; 289 dst = advance (sol->pcm_buf, rpos << hw->info.shift); 290 hw->clip (dst, src, convert_samples << hw->info.shift); 291 292 written = write(sol->fd, (char *)dst, convert_samples << hw->info.shift); 293 if (written == -1) 294 { 295 LogRel(("solaudio: Write error!\n")); 296 decr = 0; 297 break; 298 } 299 300 if (written != convert_samples << hw->info.shift) 301 { 302 int wsamples = written >> hw->info.shift; 303 int wbytes = wsamples << hw->info.shift; 304 if (wbytes != written) 305 LogRel(("solaudio: Misaligned write %d (requested %d) alignment %d\n", wbytes, written, hw->info.align + 1)); 306 307 decr -= wsamples; 308 rpos = (rpos + wsamples) % hw->samples; 309 LogFlow(("solaudio: Partial write=%d expected=%d\n", written, convert_samples << hw->info.shift)); 310 break; 311 } 312 313 rpos = (rpos + convert_samples) % hw->samples; 314 samples -= convert_samples; 315 316 sol->buffers_played++; 317 write(sol->fd, NULL, 0); /* Increment audio eof marker. */ 318 LogFlow(("solaudio: samples=%d written=%d\n", samples, written)); 319 } 320 321 LogFlow(("solaudio: run_out: decr=%d\n", decr)); 322 hw->rpos = rpos; 323 return decr; 324 } 323 for (;;) 324 { 325 cbAvail = solaudio_availbuf (pSol); 326 if (cbAvail > 0) 327 break; 328 solaudio_yield(pSol); 329 } 330 331 csAvail = cbAvail >> hw->info.shift; /* bytes => samples */ 332 csDecr = audio_MIN (csLive, csAvail); 333 csSamples = csDecr; 334 335 while (csSamples) 336 { 337 /* split request at the end of our samples buffer */ 338 csToWrite = audio_MIN (csSamples, hw->samples - hw->rpos); 339 cbToWrite = csToWrite << hw->info.shift; 340 psSrc = hw->mix_buf + hw->rpos; 341 pu8Dst = advance (pSol->pPCMBuf, hw->rpos << hw->info.shift); 342 343 hw->clip (pu8Dst, psSrc, csToWrite); 344 345 cbWritten = write (pSol->AudioDev, pu8Dst, cbToWrite); 346 if (cbWritten < 0) 347 break; 348 349 hw->rpos = (hw->rpos + csToWrite) % hw->samples; 350 csSamples -= csToWrite; 351 } 352 /* Increment eof marker for synchronous buffer processed */ 353 write (pSol->AudioDev, NULL, 0); 354 pSol->cBuffersPlayed++; 355 return csDecr; 356 } 357 325 358 326 359 static int solaudio_ctl_out (HWVoiceOut *hw, int cmd, ...) … … 334 367 audio_info_t audioInfo; 335 368 AUDIO_INITINFO(&audioInfo); 336 ioctl(sol-> fd, AUDIO_GETINFO, &audioInfo);369 ioctl(sol->AudioDev, AUDIO_GETINFO, &audioInfo); 337 370 audioInfo.play.eof = 0; 338 371 audioInfo.play.samples = 0; 339 ioctl(sol-> fd, AUDIO_SETINFO, &audioInfo);340 341 sol-> buffers_played = 0;342 audio_pcm_info_clear_buf (&hw->info, sol->p cm_buf, hw->samples);372 ioctl(sol->AudioDev, AUDIO_SETINFO, &audioInfo); 373 374 sol->cBuffersPlayed = 0; 375 audio_pcm_info_clear_buf (&hw->info, sol->pPCMBuf, hw->samples); 343 376 LogFlow(("solaudio: voice_enable\n")); 344 377 break; … … 361 394 } 362 395 396 363 397 static void *solaudio_audio_init (void) 364 398 { … … 366 400 } 367 401 402 368 403 static void solaudio_audio_fini (void *opaque) 369 404 { 370 405 (void) opaque; 371 406 } 407 372 408 373 409 static struct audio_pcm_ops solaudio_pcm_ops = { … … 384 420 NULL 385 421 }; 386 387 422 388 423 static struct audio_option solaudio_options[] = {
Note:
See TracChangeset
for help on using the changeset viewer.