Changeset 526 for OCO/trunk/drv16/wavestrm.cpp
- Timestamp:
- Jul 22, 2010, 9:33:17 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
OCO/trunk/drv16/wavestrm.cpp
r486 r526 1 1 /* SCCSID = %W% %E% */ 2 2 /**************************************************************************** 3 * 4 * Copyright (c) IBM Corporation 1994 - 1997. 5 * 6 * The following IBM OS/2 source code is provided to you solely for the 3 * * 4 * Copyright (c) IBM Corporation 1994 - 1997. * 5 * * 6 * The following IBM OS/2 source code is provided to you solely for the * 7 7 * the purpose of assisting you in your development of OS/2 device drivers. * 8 * You may use this code in accordance with the IBM License Agreement 9 * provided in the IBM Device Driver Source Kit for OS/2. 10 * 8 * You may use this code in accordance with the IBM License Agreement * 9 * provided in the IBM Device Driver Source Kit for OS/2. * 10 * * 11 11 ****************************************************************************/ 12 12 /**@internal %W% … … 14 14 * @version %I% 15 15 * @context Unless otherwise noted, all interfaces are Ring-0, 16-bit, 16 * 16 * <stack context>. 17 17 * @history 18 18 * 19 19 */ 20 20 #define INCL_NOPMAPI 21 #define INCL_DOSERRORS 21 #define INCL_DOSERRORS // for ERROR_INVALID_FUNCTION 22 22 #include <os2.h> 23 23 #include <os2me.h> 24 #include <audio.h> 24 #include <audio.h> // for #define MIDI 25 25 #include <string.h> 26 26 #include <include.h> … … 42 42 extern "C" ULONG __cdecl __saveregs OSSIDC_EntryPoint(ULONG cmd, ULONG param1, ULONG param2); 43 43 44 45 //****************************************************************************** 46 // _vRealignBuffer 47 // called just after a wave stream pause on a playback. 48 // Gets the end position of the stream when paused and a pointer to a 49 // STREAMBUFFER. Basicly this function looks at the streambuffer and if 44 #define SNDRV_PCM_STATE_XRUN 4 /* stream reached an xrun */ 45 46 //****************************************************************************** 47 // _vRealignBuffer 48 // called just after a wave stream pause on a playback. 49 // Gets the end position of the stream when paused and a pointer to a 50 // STREAMBUFFER. Basicly this function looks at the streambuffer and if 50 51 // there is any unplayed data in it it adjusts the bufpos counter. 51 52 // the donepos counter is ALWAYS set to zero. It will return 0 if all 52 53 // the data has been played and 1 if there is still some data left. 53 54 //****************************************************************************** 54 USHORT 55 USHORT WAVESTREAM::_vRealignBuffer(ULONG ulEndPos, PSTREAMBUFFER pBuffer) 55 56 { 56 57 if (ulEndPos >= pBuffer->ulDonepos) { /* all of the data has been consumed */ … … 115 116 } 116 117 117 // if there are buffer eon the done queue, pop them off the head and118 // if there are buffers on the done queue, pop them off the head and 118 119 // push them on the head of qhTempHead. This will reorder them so 119 120 // that the more recently used ones will be in the front of the queue. … … 122 123 // be returned) so put it on the Tail of the done queue. 123 124 // If the rc is 1 then put it on the head of the InProcess queue. 124 125 125 while (qhDone.IsElements()) { 126 126 pTempHead->PushOnHead(qhDone.PopHead()); … … 130 130 { 131 131 usRC = _vRealignBuffer(ulEndPos, (PSTREAMBUFFER)pTempHead->Head()); 132 if (usRC) 132 if (usRC) { 133 133 qhInProcess.PushOnHead(pTempHead->PopHead()); 134 else 135 qhDone.PushOnTail(pTempHead->PopHead()); 134 } else { 135 qhDone.PushOnHead(pTempHead->PopHead()); 136 } 136 137 } 137 138 while (qhDone.IsElements()) { … … 142 143 break; 143 144 } /* endswitch */ 145 delete pTempHead; // free the memory 146 } 147 148 void WAVESTREAM::_vUnderrunStop(PCHAR pchStr) 149 { 150 if (ulStreamState == STREAM_STOPPED) return; 151 rprintf(("%s: Underrun-stop", pchStr)); 152 //pahw->SetVolume(StreamId, getMixerStreamId(), 0); 153 pahw->Stop(StreamId); 154 ulStreamState = STREAM_STOPPED; 155 fUnderrun = TRUE; 156 _ulBytesProcessed = 0; 157 _ulBytesWritten = 0; 158 } 159 160 ULONG WAVESTREAM::_vUnderrunStart(void) 161 { 162 if (ulStreamState == STREAM_STREAMING) return 0; 163 rprintf(("Underrun-start")); 164 PSTREAMBUFFER pTemp = (PSTREAMBUFFER)qhInProcess.Head(); 165 // if(pahw->ConfigDev(StreamId, &_configinfo, (pTemp) ? pTemp->ulBuffsz : 0) == FALSE) { 166 // rprintf(("WS::Write: ConfigDev failed")); 167 // return ERROR_INSUFF_BUFFER; 168 // } 169 _configinfo.ulSRatePosition = 0; 170 // prepare wave device for playback/recording 171 if(pahw->Prepare(StreamId) == FALSE) { 172 rprintf(("WS::UR Start: Prepare failed")); 173 return ERROR_START_STREAM; 174 } 175 176 _ulBytesProcessed = 0; 177 _ulBytesWritten = 0; 178 ulStreamState = STREAM_STREAMING; 179 fUnderrun = FALSE; 180 //if (ulStreamType == STREAM_WAVE_PLAY) pahw->SetVolume(StreamId, getMixerStreamId(), volume); 181 return 0; 144 182 } 145 183 … … 150 188 // if this is a write stream call _vFillAudioBuf 151 189 //****************************************************************************** 190 static short sAddBuffersInProcess = 0; 191 static short sDbgSave; 152 192 #pragma off (unreferenced) 153 void WAVESTREAM::AddBuffers( BOOL fFirst)193 void WAVESTREAM::AddBuffers(SHORT sFirst) 154 194 #pragma on (unreferenced) 155 195 { 156 196 ULONG ulSpace, ulBytesWritten; 157 197 ULONG ulDAZ; 158 159 //dgprintf(("WS:AddBuffers First=%d, SampleSize=%lx", fFirst, _configinfo.ulSampleSize)); 160 161 ulBytesWritten = 0; 162 if (ulStreamType & STREAM_WRITE) 163 { 164 // get the space available in the hardware buffer 165 // only call GetSpace once because the amount of free space in 166 // the hardware buffer is a moving target and calling it more than once 167 // could keep us in this loop writing 4 or 8 bytes at a time. 168 // In extream cases we will stay stuck in this loop long enough to casue a trap rjj 169 if (pahw->GetSpace(StreamId, &_configinfo, &ulSpace) == FALSE) 170 { 171 dgprintf(("WAVESTREAM::AddBuffers GetSpace failed")); 172 return; 173 } 174 ulSpace &= (~(_configinfo.ulSampleSize - 1)); 198 ULONG ulStatus; 199 200 //dprintf(("WS:AddBuffers First=%d, SampleSize=%lx", sFirst, _configinfo.ulSampleSize)); 201 202 if (sAddBuffersInProcess) { 203 // This routine cannot be reentered 204 // Some systems generate an extra interrupt causing this routine to be reentered 205 // so we ignore the call that causes us to be reentered 206 rprintf(("WS::ABS InProcess Now=%x Save=%x", sFirst, sDbgSave)); 207 return; 208 } 209 sAddBuffersInProcess++; 210 sDbgSave = sFirst; 211 212 ulBytesWritten = 0; 213 if (ulStreamType & STREAM_WRITE) 214 { 215 // get the space available in the hardware buffer 216 // only call GetSpace once because the amount of free space in 217 // the hardware buffer is a moving target and calling it more than once 218 // could keep us in this loop writing 4 or 8 bytes at a time. 219 // In extream cases we will stay stuck in this loop long enough to casue a trap rjj 220 if (pahw->GetSpace(StreamId, &_configinfo, &ulSpace) == FALSE) { 221 rprintf(("WS::ABS GetSpace failed")); 222 return; 223 } 224 ulSpace &= (~(_configinfo.ulSampleSize - 1)); 225 #if 1 226 /* DAZ testing -- underrun detection */ 227 if (ulSpace == 0) { 228 OSS16_WaveGetStatus(StreamId, &ulStatus); 229 rprintf(("WS::ABS ulSpace=0 state=%lx u32status=%lx", ulStreamState, ulStatus)); 230 231 _vUnderrunStop("WS:ABS"); 232 _vUnderrunStart(); 233 234 if (pahw->GetSpace(StreamId, &_configinfo, &ulSpace) == FALSE) { 235 rprintf(("WS::ABS GetSpace failed")); 236 return; 237 } 238 ulSpace &= (~(_configinfo.ulSampleSize - 1)); 239 if (ulSpace ==0) rprintf(("WS::ABS still no space")); 240 } 241 #endif 175 242 ulDAZ = 0; 176 177 243 while (ulSpace && qhInProcess.IsElements()) 244 { 178 245 if (ulDAZ++ > 20) { 179 dgprintf(("WAVESTREAM::AddBuffers DAZ break")); // Temporary hack to prevent lockups when uniaud32 stops (underrun) 246 rprintf(("WS::ABS DAZ break")); // Temporary hack to prevent lockups when uniaud32 stops (underrun) 247 int3(); /* should never happen */ 180 248 break; 181 249 } 182 // First time is in task time. For I7 need to give time for interrupt time 183 if (fFirst == TRUE) //PS+++ 184 { 185 //cli(); 186 DevHelp_ProcBlock (0x5541, 20, 0); // ok since the first call is at task time 187 ulBytesWritten = AddBuffer(ulSpace); 188 return; 250 ulBytesWritten = AddBuffer(ulSpace); 251 if (ulBytesWritten == (ULONG)-1) { 252 OSS16_WaveGetStatus(StreamId, &ulStatus); 253 rprintf(("WS::ABS AddBuffer returns -1 u32Status=%lx", ulStatus)); 254 break; 189 255 } 190 ulBytesWritten = AddBuffer(ulSpace); 191 if (ulBytesWritten == (ULONG)-1) break; 192 ulSpace -= ulBytesWritten; 193 ulSpace &= ( ~(_configinfo.ulSampleSize - 1)); 194 } 195 196 } 197 } 198 199 //****************************************************************************** 200 // write one buffer to the audio buffer 1 201 // the caller of this function MUST make sure it ok to write the audio buffer.. 202 // _AudioBufWrite will not check if there is room in the audio buffer of if 203 // there are buffers on pHead... BEWARE 256 ulSpace -= ulBytesWritten; 257 ulSpace &= ( ~(_configinfo.ulSampleSize - 1)); 258 } 259 // if (ulSpace) { 260 // dprintf(("WAVESTREAM::AddBuffers done. ulSpace=%lx", ulSpace)); 261 // } 262 } 263 sAddBuffersInProcess--; 264 } 265 266 //****************************************************************************** 267 // write one buffer to the audio buffer in uniaud32 204 268 //****************************************************************************** 205 269 ULONG WAVESTREAM::AddBuffer(ULONG ulSpace) 206 270 { 207 208 209 271 PSTREAMBUFFER pTemp = (PSTREAMBUFFER)qhInProcess.Head(); 272 ULONG pDataBuf; 273 ULONG ulBuffLeft; 210 274 ULONG ulBytesWritten; 211 //DAZ ULONG ulStartPos; 212 213 /* make sure we have a buffer to copy from */ 214 if (!pTemp) 215 { 216 return (ULONG)-1; 217 } 275 276 /* make sure we have a buffer to copy from */ 277 if (!pTemp) return (ULONG)-1; 218 278 219 279 /* make sure there is space in the output buffer */ 220 if (!ulSpace) 221 { 222 return (ULONG)-1; 223 } 280 if (!ulSpace) return (ULONG)-1; 224 281 225 282 /* PS+++ if input buffer is ZERO do nothing and ask for give new buffer, See REMARK in mmpm2.inf */ 226 if (!pTemp->ulBuffsz) 227 { 228 qhDone.PushOnTail(qhInProcess.PopHead()); 229 return (ULONG)-1; 230 } 231 232 /* DAZ */ 233 #if 0 234 // get the starting position. Call WaveGetHwPtr. if we get a bad rc then we bail out. 235 if(pahw->GetHwPtr(StreamId, &_configinfo, &ulStartPos) == FALSE) 236 { 237 dgprintf(("WAVESTREAM::AddBuffer Err in GetHwPtr")); 238 DebugInt3(); 239 return (ULONG)-1; 240 } 241 #endif 242 243 // get the buffer pointer and amount of data remaining 244 pDataBuf = (ULONG)pTemp->pBuffptr + pTemp->ulBuffpos; /* points to the beginning of data in src buffer */ 245 ulBuffLeft = pTemp->ulBuffsz - pTemp->ulBuffpos; /* amount of src data left to transfer */ 246 //dgprintf(("WS::AddBuffer buf=%lx remain=%lx, space=%lx bp=%lx dp=%lx size=%lx", pTemp->pBuffptr, ulBuffLeft, ulSpace, pTemp->ulBuffpos, pTemp->ulDonepos, pTemp->ulBuffsz)); 247 ulBuffLeft = min(ulBuffLeft, ulSpace); /* the smaller of src data left or dst space available */ 248 249 if (pahw->Transfer(StreamId, &_configinfo, pDataBuf, ulBuffLeft, &ulBytesWritten) == FALSE) 250 { 283 if (!pTemp->ulBuffsz) { 284 qhDone.PushOnTail(qhInProcess.PopHead()); 285 return 0; 286 } 287 if (pTemp->ulBuffsz < (_configinfo.ulBytesPerIRQ*2)) { 288 rprintf(("WS::AB: BufferMode=1")); 289 usBufferMode = 1; 290 } 291 292 // get the buffer pointer and amount of data remaining 293 pDataBuf = (ULONG)pTemp->pBuffptr + pTemp->ulBuffpos; /* points to the beginning of data in src buffer */ 294 ulBuffLeft = pTemp->ulBuffsz - pTemp->ulBuffpos; /* amount of src data left to transfer */ 295 //dprintf(("WS::AddBuffer buf=%lx remain=%lx, space=%lx bp=%lx dp=%lx size=%lx", pTemp->pBuffptr, ulBuffLeft, ulSpace, pTemp->ulBuffpos, pTemp->ulDonepos, pTemp->ulBuffsz)); 296 ulBuffLeft = min(ulBuffLeft, ulSpace); /* the smaller of src data left or dst space available */ 297 298 if (!ulBuffLeft) { 299 qhDone.PushOnTail(qhInProcess.PopHead()); 300 return 0; 301 } 302 303 if (pahw->Transfer(StreamId, &_configinfo, pDataBuf, ulBuffLeft, &ulBytesWritten) == FALSE) { 251 304 // This could mean that the hardware has underrun TODO: implement underrun logic 252 dgprintf(("WS::AddBuffer: pahw->Transfer failed"));253 254 255 if (ulBytesWritten == 0) 256 305 rprintf(("WS::AB: pahw->Transfer failed")); 306 return (ULONG)-1; 307 } 308 //dprintf(("WS::AB: %lx of %lx bytes written", ulBytesWritten, ulBuffLeft)); 309 if (ulBytesWritten == 0) { 257 310 // This could mean that the hardware has underrun TODO: implement underrun logic 258 dgprintf(("WS::AddBuffer: 0 of %lx bytes written by transfer", ulBuffLeft));259 return (ULONG)-1; /* DAZ check into returning zero, returning 0 may cause lockup */260 261 //d gprintf(("WS::AddBuffer added %lx from %lx BuffPos=%lx sz=%lx bw=%lx dp=%lx", ulBytesWritten, pTemp->pBuffptr, pTemp->ulBuffpos, pTemp->ulBuffsz, _ulBytesWritten, pTemp->ulDonepos));311 //rprintf(("WS::AddBuffer: 0 of %lx bytes written by transfer", ulBuffLeft)); 312 return (ULONG)-1; 313 } 314 //dprintf(("WS::AddBuffer added %lx from %lx BuffPos=%lx sz=%lx bw=%lx dp=%lx", ulBytesWritten, pTemp->pBuffptr, pTemp->ulBuffpos, pTemp->ulBuffsz, _ulBytesWritten, pTemp->ulDonepos)); 262 315 263 316 _ulBytesWritten += ulBytesWritten; /* update the running counter */ 264 265 266 267 268 269 270 //d gprintf(("WS::AddBuffer done with buffer %lx dp=%lx", pTemp->pBuffptr, pTemp->ulDonepos));271 272 273 317 pTemp->ulBuffpos += ulBytesWritten; /* update the buffer pos counter */ 318 pTemp->ulDonepos = _ulBytesWritten; /* update the done Position for returning the buffer */ 319 320 // check to see if the whole buffer has been copied and needs to be put on the done queue 321 if (pTemp->ulBuffpos >= (pTemp->ulBuffsz /* & 0xFFFFFFFC*/)) /* DAZ */ 322 { 323 //dprintf(("WS::AddBuffer done with buffer %lx dp=%lx", pTemp->pBuffptr, pTemp->ulDonepos)); 324 qhDone.PushOnTail(qhInProcess.PopHead()); 325 } 326 return ulBytesWritten; 274 327 } 275 328 //****************************************************************************** … … 279 332 BOOL WAVESTREAM::_vReadAudioBuf(void) 280 333 { 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 334 PSTREAMBUFFER pTemp = (PSTREAMBUFFER)qhInProcess.Head(); 335 ULONG pDataBuf; 336 ULONG ulBuffLeft, ulBytesRead; 337 338 if(!pTemp) return FALSE; 339 340 // get the buffer pointer and amount of data remaining 341 pDataBuf = (ULONG)pTemp->pBuffptr + pTemp->ulBuffpos; 342 ulBuffLeft = pTemp->ulBuffsz - pTemp->ulBuffpos; 343 344 // read wave data 345 if(pahw->Transfer(StreamId, &_configinfo, pDataBuf, ulBuffLeft, &ulBytesRead) == FALSE) 346 { 347 return FALSE; /* No more data */ 348 } 349 if(ulBytesRead == 0) { 350 return FALSE; /* No more data */ 351 } 299 352 if (ulBytesRead > ulBuffLeft) { 300 301 } 302 303 304 305 353 return FALSE; /* Internal error */ 354 } 355 356 // update the buffer pos counter 357 pTemp->ulBuffpos += ulBytesRead; 358 _ulBytesProcessed += ulBytesRead; 306 359 307 360 //dprintf(("_vReadAudioBuf %lx Requested=%lx Read=%lx Remain=%lx Processed=%lx", pDataBuf, ulBuffLeft, ulBytesRead, pTemp->ulBuffsz-pTemp->ulBuffpos, _ulBytesProcessed)); 308 361 309 310 311 312 313 314 362 if(pTemp->ulBuffpos == pTemp->ulBuffsz) { 363 qhDone.PushOnTail(qhInProcess.PopHead()); 364 ReturnBuffer(); 365 } 366 367 return TRUE; 315 368 } 316 369 //****************************************************************************** … … 327 380 ULONG ulDAZ; 328 381 329 //d dprintf(("WAVESTREAM::Process Start"));330 331 332 333 334 382 //dprintf(("WAVESTREAM::Process Start")); 383 384 // get the stream position. if we get a bad rc or the position is 0 385 // then we bail out. Hopefully this will be better next time. 386 // GetPostiion returns the adjusted hw pointer from the ALSA status ioctl 387 // This is really a running total of bytes consumed by the hardware. 335 388 // DAZ - Note that this is a 32 bit counter and will wrap at sometime. ALSA 336 389 // attempts to wrap this counter intelligently. I haven't determined what 337 390 // effect, if any, the wrapping of this counter will have playing a stream. 338 if(pahw->GetPosition(StreamId, &_configinfo, &ulBytes) == FALSE) 339 { 340 ddprintf(("Error No bytes processed")); 341 DebugInt3(); 342 return; 343 } 344 _ulBytesProcessed = ulBytes; 345 346 switch (ulStreamType & STREAM_WRITE) 347 { 348 case STREAM_WRITE: 349 if (qhInProcess.IsElements()) 350 { 351 AddBuffers(FALSE); 352 } 353 // Return any buffers that have been completely written to uniaud32 391 if(pahw->GetPosition(StreamId, &_configinfo, &ulBytes) == FALSE) 392 { 393 //dprintf(("Error No bytes processed")); 394 DebugInt3(); 395 return; 396 } 397 _ulBytesProcessed = ulBytes; 398 399 switch (ulStreamType & STREAM_WRITE) 400 { 401 case STREAM_WRITE: 402 if(!qhInProcess.IsElements() && !qhDone.IsElements()) { 403 _vUnderrunStop("WS:Process"); 404 break; 405 } 406 if (qhInProcess.IsElements()) AddBuffers(1); 407 // Return any buffers that have been completely written to uniaud32 408 //dprintf(("WS::Process usBufferMode=%x", usBufferMode)); 354 409 while (qhDone.IsElements()) { 355 410 pTemp = (PSTREAMBUFFER)qhDone.Head(); /* get a pointer to the first completed buffer */ 356 411 // Hang on to the last buffer until the hardware is done writing the data 357 412 // We do this because MMPM uses the return of the last buffer to determine when we are 358 413 // done playing the stream 359 if ((qhDone.Head() == qhDone.Tail()) && !qhInProcess.IsElements() && (_ulBytesProcessed < pTemp->ulDonepos)) break; /* only one buffer left */ 414 if ((qhDone.Head() == qhDone.Tail()) && !qhInProcess.IsElements()) { /* only one buffer left */ 415 if (_ulBytesProcessed < pTemp->ulDonepos) break; 416 } else { /* not the last buffer */ 417 /* if the buffer is bigger than BytesPerIRQ and it's not finished yet, hang on to it */ 418 if (!usBufferMode && (_ulBytesProcessed < pTemp->ulDonepos)) break; 419 //if ((_ulBytesProcessed + _configinfo.ulBytesPerIRQ) < pTemp->ulDonepos) break; 420 } 360 421 ReturnBuffer(); 361 422 } 362 363 423 break; 424 case STREAM_READ: 364 425 ulDAZ = 0; 365 426 while(_vReadAudioBuf()) { 366 427 if (ulDAZ++ > 20) { /* temporary hack to prevent hangs when uniaud32 stops (overruns) */ 367 ddprintf(("WAVESTREAM::Process Read DAZ Break"));428 rprintf(("WS::Process Read DAZ Break")); 368 429 break; 369 430 } 370 431 } 371 372 373 374 375 376 377 //ddprintf(("WAVESTREAM::Process End"));432 break; 433 default: 434 break; 435 } /* endswitch */ 436 437 ProcessEvents(); 438 //dprintf(("WAVESTREAM::Process End")); 378 439 } 379 440 //****************************************************************************** … … 383 444 #pragma on (unreferenced) 384 445 { 385 386 387 446 PSTREAMBUFFER pStreamBuf = new STREAMBUFFER(uLength, pbuf); 447 448 return Write(pStreamBuf); 388 449 } 389 450 //****************************************************************************** … … 391 452 ULONG WAVESTREAM::Write(PSTREAMBUFFER pStreamBuf) 392 453 { 393 qhInProcess.PushOnTail((PQUEUEELEMENT)pStreamBuf); 394 // dprintf2(("WAVESTREAM::Write: Push on tail %lx %ld", ((PSTREAMBUFFER)qhInProcess.Tail())->pBuffptr, ((PSTREAMBUFFER)qhInProcess.Tail())->ulBuffsz)); 395 return 0; 454 455 #if 1 456 ULONG ulStatus; 457 458 ulStatus = 0; 459 if (OSS16_WaveGetStatus(StreamId, &ulStatus) != OSSERR_SUCCESS) ulStatus = SNDRV_PCM_STATE_XRUN; 460 //dprintf(("WS::Write: status=%lx", ulStatus)); 461 if (ulStatus == SNDRV_PCM_STATE_XRUN) { 462 rprintf(("WS::Write: Xrun detect")); 463 _vUnderrunStop("WS:Write"); 464 fUnderrun = TRUE; 465 } 466 #endif 467 qhInProcess.PushOnTail((PQUEUEELEMENT)pStreamBuf); 468 if (fUnderrun) { 469 _vUnderrunStart(); 470 AddBuffers(2); 471 } 472 return 0; 396 473 } 397 474 //****************************************************************************** … … 399 476 ULONG WAVESTREAM::Read(PSTREAMBUF pbuf, unsigned uLength) 400 477 { 401 402 403 478 qhInProcess.PushOnTail((PQUEUEELEMENT)new STREAMBUFFER(uLength, pbuf)); 479 //dprintf2(("WAVESTREAM::Read: Push on tail %lx %lx", pbuf, uLength)); 480 return 0; 404 481 } 405 482 //****************************************************************************** … … 419 496 ULONG WAVESTREAM::GetCurrentTime() 420 497 { 421 ULONG Seconds, MilliSeconds, Overflow, Processed; 422 423 //PS++ optimize code 424 Processed = _ulBytesProcessed; 425 if (ulStreamState == STREAM_STREAMING) // if the stream is active 426 { 427 if (ulStreamType & STREAM_WRITE) 428 { 429 if (pahw->GetPosition(StreamId, &_configinfo, &Processed) == FALSE) 430 { 431 //DebugInt3(); 432 Processed = _ulBytesProcessed; //last known position 433 } 434 } 435 } 436 437 // if we haven't processed anything then just return _ulTimeBase 438 if(Processed == 0) 439 return(_ulTimeBase); 440 441 Seconds = Processed / _configinfo.ulPCMConsumeRate; 442 Overflow = Processed - (Seconds * _configinfo.ulPCMConsumeRate); 443 MilliSeconds = (Overflow * 1000) / _configinfo.ulPCMConsumeRate; 444 MilliSeconds += (Seconds * 1000); 445 return (MilliSeconds + _ulTimeBase); 446 } 447 //****************************************************************************** 448 //****************************************************************************** 449 ULONG WAVESTREAM::GetCurrentPos(void) 450 { 451 ULONG Processed; 498 ULONG Seconds, MilliSeconds, Overflow, Processed; 452 499 453 500 //PS++ optimize code 454 501 Processed = _ulBytesProcessed; 455 if (ulStreamState == STREAM_STREAMING) // if the stream is active 502 if (ulStreamState == STREAM_STREAMING) // if the stream is active 503 { 504 if (ulStreamType & STREAM_WRITE) 505 { 506 if (pahw->GetPosition(StreamId, &_configinfo, &Processed) == FALSE) 507 { 508 //DebugInt3(); 509 Processed = _ulBytesProcessed; //last known position 510 } 511 } 512 } 513 514 // if we haven't processed anything then just return _ulTimeBase 515 if(Processed == 0) 516 return(_ulTimeBase); 517 518 Seconds = Processed / _configinfo.ulPCMConsumeRate; 519 Overflow = Processed - (Seconds * _configinfo.ulPCMConsumeRate); 520 MilliSeconds = (Overflow * 1000) / _configinfo.ulPCMConsumeRate; 521 MilliSeconds += (Seconds * 1000); 522 return (MilliSeconds + _ulTimeBase); 523 } 524 //****************************************************************************** 525 //****************************************************************************** 526 ULONG WAVESTREAM::GetCurrentPos(void) 527 { 528 ULONG Processed; 529 530 //PS++ optimize code 531 Processed = _ulBytesProcessed; 532 if (ulStreamState == STREAM_STREAMING) // if the stream is active 456 533 { 457 534 if (ulStreamType & STREAM_WRITE) … … 478 555 if(!pTemp) 479 556 { 480 557 pTemp = (PSTREAMBUFFER)qhInProcess.Head(); 481 558 } 482 559 if(pTemp) 483 560 { 484 561 writepos = pTemp->ulBuffpos; 485 562 } 486 563 sti(); … … 495 572 void WAVESTREAM::SetCurrentTime(ULONG time) 496 573 { 497 //d dprintf(("SetCurrentTime: %lx", time));498 574 //dprintf(("SetCurrentTime: %lx", time)); 575 _ulTimeBase = time; 499 576 } 500 577 //****************************************************************************** … … 502 579 ULONG WAVESTREAM::StartStream() 503 580 { 504 505 506 507 508 ddprintf(("StartStream: already playing!!"));509 510 511 512 513 514 515 516 ddprintf(("StartStream: ConfigDev failed!!"));517 581 PSTREAMBUFFER pTemp = (PSTREAMBUFFER)qhInProcess.Head(); 582 583 if(ulStreamState == STREAM_STREAMING) 584 { 585 //dprintf(("StartStream: already playing!!")); 586 return NO_ERROR; 587 } 588 589 // configure the wave device 590 // (NOTE: Must call this function; sample rate position is reset there) 591 if(pahw->ConfigDev(StreamId, &_configinfo, (pTemp) ? pTemp->ulBuffsz : 0) == FALSE) 592 { 593 rprintf(("StartStream: ConfigDev failed!!")); 594 return ERROR_INSUFF_BUFFER; 518 595 //goto fail; 519 520 521 522 523 ddprintf(("StartStream: Prepare failed!!"));524 525 526 527 596 } 597 // prepare wave device for playback/recording 598 if(pahw->Prepare(StreamId) == FALSE) 599 { 600 rprintf(("StartStream: Prepare failed!!")); 601 goto fail; 602 } 603 604 _ulBytesProcessed = 0; 528 605 _ulBytesWritten = 0; 529 530 ulStreamState = STREAM_STREAMING; 531 //Adding the first buffer also starts playback 532 if (ulStreamType == STREAM_WAVE_PLAY) 533 { 534 pahw->SetVolume(StreamId, getMixerStreamId(), volume); //PS 535 AddBuffers(TRUE); 536 //Must set volume after adding buffers (voices inside sblive driver might not 537 //be allocated otherwise (first start) ) 538 // dprintf(("SetVolume %lx",volume)); 539 // PS, removing to high 540 // pahw->SetVolume(StreamId, getMixerStreamId(), volume); 541 } 542 else 543 { 544 //dprintf(("Starting Rec Stream")); 545 ulSavedInputGain = pahw->QueryVolume(StreamId, getMixerStreamId()); 546 pahw->SetInputSrc(StreamId, getMixerStreamId(), inputsrc); 547 pahw->SetVolume(StreamId, getMixerStreamId(), inputgain); 606 fUnderrun = FALSE; 607 usBufferMode = 0; 608 609 ulStreamState = STREAM_STREAMING; 610 //Adding the first buffer also starts playback 611 if (ulStreamType == STREAM_WAVE_PLAY) 612 { 613 //DAZ moved from AddBuffers, for I7, might not be needed 614 //DevHelp_ProcBlock (0x5541, 20, 0); 615 pahw->SetVolume(StreamId, getMixerStreamId(), volume); //PS 616 AddBuffers(3); 617 } 618 else 619 { 620 //dprintf(("Starting Rec Stream")); 621 ulSavedInputGain = pahw->QueryVolume(StreamId, getMixerStreamId()); 622 pahw->SetInputSrc(StreamId, getMixerStreamId(), inputsrc); 623 pahw->SetVolume(StreamId, getMixerStreamId(), inputgain); 548 624 549 625 if(pahw->Start(StreamId) != TRUE) 550 626 { 551 dprintf(("pahw->Start failed!!"));552 553 554 555 627 rprintf(("pahw->Start failed!!")); 628 goto fail; 629 } 630 } 631 return NO_ERROR; 556 632 557 633 fail: 558 559 634 DebugInt3(); 635 return ERROR_START_STREAM; 560 636 } 561 637 //****************************************************************************** … … 563 639 ULONG WAVESTREAM::StopStream(PCONTROL_PARM pControl) 564 640 { 565 if(ulStreamState == STREAM_STOPPED) { 566 dprintf(("WAVESTREAM::StopStream %lx (already stopped)", StreamId)); 567 pControl->ulTime = GetCurrentTime(); 568 return NO_ERROR; 569 } 570 //silence wave stream before stopping it (removes clicks) 571 if(ulStreamType == STREAM_WAVE_PLAY) { 572 pahw->SetVolume(StreamId, getMixerStreamId(), 0); 573 } 574 else { 575 pahw->SetVolume(StreamId, getMixerStreamId(), ulSavedInputGain); 576 } 577 pahw->Stop(StreamId); 578 579 ulStreamState = STREAM_STOPPED; 580 //ddprintf(("WAVESTREAM::StopStream %lx", StreamId)); 581 582 ReturnBuffers(); 583 pControl->ulTime = GetCurrentTime(); 584 585 // We need to set _ulBytesProcessed to 0 here. if we do not 586 // and MMPM restarts the stream by sending a DDCMD_SETUP followed By 587 // DDCMD_ENABLE_EVENT the event time will get screwed up. rjj 588 _ulBytesProcessed = 0; 641 if(ulStreamState == STREAM_STOPPED) { 642 //dprintf(("WS::StopStream %lx (already stopped)", StreamId)); 643 fUnderrun = FALSE; 644 pControl->ulTime = GetCurrentTime(); 645 return NO_ERROR; 646 } 647 //silence wave stream before stopping it (removes clicks) 648 if(ulStreamType == STREAM_WAVE_PLAY) { 649 pahw->SetVolume(StreamId, getMixerStreamId(), 0); 650 } 651 else { 652 pahw->SetVolume(StreamId, getMixerStreamId(), ulSavedInputGain); 653 } 654 pahw->Stop(StreamId); 655 656 ulStreamState = STREAM_STOPPED; 657 fUnderrun = FALSE; 658 //dprintf(("WAVESTREAM::StopStream %lx", StreamId)); 659 660 ReturnBuffers(); 661 pControl->ulTime = GetCurrentTime(); 662 663 // We need to set _ulBytesProcessed to 0 here. if we do not 664 // and MMPM restarts the stream by sending a DDCMD_SETUP followed By 665 // DDCMD_ENABLE_EVENT the event time will get screwed up. rjj 666 _ulBytesProcessed = 0; 589 667 _ulBytesWritten = 0; 590 668 return NO_ERROR; 591 669 } 592 670 //****************************************************************************** … … 594 672 ULONG WAVESTREAM::PauseStream(PCONTROL_PARM pControl) 595 673 { 596 ULONG ulEndPos, ulEndPos2; 597 598 if(ulStreamState == STREAM_PAUSED) { 599 dprintf(("WAVESTREAM::PauseStream %lx (already paused)", StreamId)); 600 pControl->ulTime = GetCurrentTime(); 601 return NO_ERROR; 602 } 603 604 pahw->GetPosition(StreamId, &_configinfo, &ulEndPos); 605 //silence wave stream before stopping it (removes clicks) 606 pahw->SetVolume(StreamId, getMixerStreamId(), 0); 607 pahw->Stop(StreamId); 608 674 ULONG ulEndPos; 675 676 if(ulStreamState == STREAM_PAUSED) { 677 dprintf(("WS::PauseStream %lx (already paused)", StreamId)); 678 fUnderrun = FALSE; 679 pControl->ulTime = GetCurrentTime(); 680 return NO_ERROR; 681 } 682 683 pahw->GetPosition(StreamId, &_configinfo, &ulEndPos); 684 //silence wave stream before stopping it (removes clicks) 685 pahw->SetVolume(StreamId, getMixerStreamId(), 0); 686 pahw->Stop(StreamId); 687 688 #if 0 609 689 /* DAZ test code begin */ 610 690 if (pahw->GetPosition(StreamId, &_configinfo, &ulEndPos2) == FALSE) ulEndPos2 = 0; 611 691 if (ulEndPos2 != ulEndPos) { 612 ddprintf(("WAVESTREAM::PauseStream %lx!=%lx", ulEndPos, ulEndPos2));692 dprintf(("WS::PauseStream %lx!=%lx", ulEndPos, ulEndPos2)); 613 693 if (ulEndPos2) ulEndPos = ulEndPos2; 614 694 } 615 695 /* DAZ test code end */ 616 617 ulStreamState = STREAM_PAUSED; 618 619 ddprintf(("WAVESTREAM::PauseStream %lx", StreamId)); 620 621 _ulBytesProcessed = ulEndPos; 622 623 _vRealignPausedBuffers(ulEndPos); 624 625 pControl->ulTime = GetCurrentTime(); 626 627 _ulBytesProcessed = 0; 696 #endif 697 698 ulStreamState = STREAM_PAUSED; 699 700 dprintf(("WS::PauseStream %lx", StreamId)); 701 702 _ulBytesProcessed = ulEndPos; 703 704 _vRealignPausedBuffers(ulEndPos); 705 706 pControl->ulTime = GetCurrentTime(); 707 708 _ulBytesProcessed = 0; 628 709 _ulBytesWritten = 0; 629 630 return NO_ERROR; 710 fUnderrun = FALSE; 711 712 return NO_ERROR; 631 713 } 632 714 //****************************************************************************** … … 634 716 ULONG WAVESTREAM::ResumeStream(void) 635 717 { 636 #ifdef DEBUG 637 //dprintf(("WAVESTREAM::ResumeStream %lx", StreamId)); 638 #endif 639 return StartStream(); 718 //dprintf(("WAVESTREAM::ResumeStream %lx", StreamId)); 719 return StartStream(); 640 720 } 641 721 //****************************************************************************** … … 643 723 BOOL WAVESTREAM::SetProperty(int type, ULONG value, ULONG reserved) 644 724 { 645 646 647 648 dprintf(("WAVESTREAM::SetProperty() Vol: %0lx",value));649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 725 switch(type) { 726 case PROPERTY_VOLUME: 727 volume = value; 728 dprintf(("WS::SetProperty() Vol: %0lx",value)); 729 if(ulStreamState == STREAM_STREAMING && ulStreamType == STREAM_WAVE_PLAY) { 730 MixerSetWaveVolume(getMixerStreamId(), StreamId, volume); 731 } 732 break; 733 734 case PROPERTY_INPUTSRC: 735 inputsrc = value; 736 break; 737 738 case PROPERTY_INPUTGAIN: 739 inputgain = value; 740 break; 741 742 default: 743 return STREAM::SetProperty(type, value, reserved); 744 } 745 return TRUE; 666 746 } 667 747 //****************************************************************************** … … 669 749 ULONG WAVESTREAM::GetProperty(int type) 670 750 { 671 672 673 674 675 676 677 678 679 680 681 682 683 751 switch(type) { 752 case PROPERTY_FREQUENCY: 753 return _configinfo.ulSampleRate; 754 755 case PROPERTY_INPUTSRC: 756 return inputsrc; 757 758 case PROPERTY_INPUTGAIN: 759 return inputgain; 760 761 default: 762 return STREAM::GetProperty(type); 763 } 684 764 } 685 765 //****************************************************************************** … … 688 768 STREAM(streamtype, filesysnum, mixerStreamId) 689 769 { 690 // get the pointer to the hardware object 691 pahw = (WAVEAUDIO*)GetHardwareDevice(streamtype); 692 693 _fmemset(&_configinfo, 0, sizeof(_configinfo)); 694 _configinfo.ulSampleRate = pinit->lSRate; 695 _configinfo.ulBitsPerSample = pinit->lBitsPerSRate; 696 _configinfo.ulNumChannels = pinit->sChannels; 697 _configinfo.ulDataType = pinit->sMode; 698 _ulBytesWritten = 0; 699 _ulBytesProcessed = 0; 700 _ulTimeBase = 0; 701 ulSavedInputGain = 0; 702 703 _configinfo.pConversionBuffer = 0; 704 pahw->SetupConversion(&_configinfo, pinit->ulOperation, pinit->sMode, pinit->sChannels, pinit->lBitsPerSRate); 705 706 if(_configinfo.usConversion != CONVERT_NONE) 707 {//allocate conversion buffer 708 PVOID pSelOff; 709 LIN linAddr; 710 711 if(DevHelp_VMAlloc((VMDHA_FIXED | VMDHA_CONTIG), CONVERSION_BUFFER_SIZE, (ULONG)-1L, &linAddr, &pSelOff) != 0) 712 { 713 dgprintf(("Error in DevHelp_VMAlloc Conversion Buffer")); 714 DebugInt3(); //should never happen!! 715 _configinfo.usConversion = CONVERT_NONE; 716 } 717 else _configinfo.pConversionBuffer = linAddr; 718 } 719 if(_configinfo.fSampleRateConversion == TRUE) 720 {//allocate buffer for sample rate conversion 721 PVOID pSelOff; 722 LIN linAddr; 723 724 if (DevHelp_VMAlloc((VMDHA_FIXED | VMDHA_CONTIG), CONVERSION_BUFFER_SIZE, (ULONG)-1L, &linAddr, &pSelOff) != 0) 725 { 726 dgprintf(("Error in DevHelp_VMAlloc SR Conversion Buffer")); 727 DebugInt3(); //should never happen!! 728 } 729 else _configinfo.pSRateConvBuffer = linAddr; 730 } 731 732 pinit->ulFlags |= pahw->QueryDataFlags(pinit->ulOperation, pinit->sMode, pinit->lBitsPerSRate); 733 734 StreamId = 0; 735 736 if(pahw->Open(current_device, ulStreamType, ulSysFileNum, &StreamId) != TRUE) 737 { 738 dprintf(("pahw->Open failed!!")); 739 DebugInt3(); 740 } 770 // get the pointer to the hardware object 771 pahw = (WAVEAUDIO*)GetHardwareDevice(streamtype); 772 773 _fmemset(&_configinfo, 0, sizeof(_configinfo)); 774 _configinfo.ulSampleRate = pinit->lSRate; 775 _configinfo.ulBitsPerSample = pinit->lBitsPerSRate; 776 _configinfo.ulNumChannels = pinit->sChannels; 777 _configinfo.ulDataType = pinit->sMode; 778 _ulBytesWritten = 0; 779 _ulBytesProcessed = 0; 780 _ulTimeBase = 0; 781 ulSavedInputGain = 0; 782 fUnderrun = FALSE; 783 usBufferMode = 0; 784 785 _configinfo.pConversionBuffer = 0; 786 pahw->SetupConversion(&_configinfo, pinit->ulOperation, pinit->sMode, pinit->sChannels, pinit->lBitsPerSRate); 787 788 if(_configinfo.usConversion != CONVERT_NONE) 789 {//allocate conversion buffer 790 PVOID pSelOff; 791 LIN linAddr; 792 793 if(DevHelp_VMAlloc((VMDHA_FIXED | VMDHA_CONTIG), CONVERSION_BUFFER_SIZE, (ULONG)-1L, &linAddr, &pSelOff) != 0) 794 { 795 rprintf(("Error in DevHelp_VMAlloc Conversion Buffer")); 796 DebugInt3(); //should never happen!! 797 _configinfo.usConversion = CONVERT_NONE; 798 } 799 else _configinfo.pConversionBuffer = linAddr; 800 } 801 if(_configinfo.fSampleRateConversion == TRUE) 802 {//allocate buffer for sample rate conversion 803 PVOID pSelOff; 804 LIN linAddr; 805 806 if (DevHelp_VMAlloc((VMDHA_FIXED | VMDHA_CONTIG), CONVERSION_BUFFER_SIZE, (ULONG)-1L, &linAddr, &pSelOff) != 0) 807 { 808 rprintf(("Error in DevHelp_VMAlloc SR Conversion Buffer")); 809 DebugInt3(); //should never happen!! 810 } 811 else _configinfo.pSRateConvBuffer = linAddr; 812 } 813 814 pinit->ulFlags |= pahw->QueryDataFlags(pinit->ulOperation, pinit->sMode, pinit->lBitsPerSRate); 815 816 StreamId = 0; 817 818 if(pahw->Open(current_device, ulStreamType, ulSysFileNum, &StreamId) != TRUE) 819 { 820 rprintf(("pahw->Open failed!!")); 821 DebugInt3(); 822 } 741 823 742 824 //dprintf(("WAVESTREAM stream %lx ctor %lx: rate %d bps %d numchan %d type %x", hstream, StreamId, (USHORT)_configinfo.ulSampleRate, (USHORT)_configinfo.ulBitsPerSample, (USHORT)_configinfo.ulNumChannels, (USHORT)_configinfo.ulNumChannels, (USHORT)_configinfo.ulDataType)); … … 747 829 { 748 830 //dprintf(("WAVESTREAM stream %x dtor %lx", hstream, StreamId)); 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 } 767 //****************************************************************************** 768 //****************************************************************************** 769 831 if(_configinfo.pConversionBuffer) { 832 if(DevHelp_VMFree(_configinfo.pConversionBuffer) != 0) { 833 DebugInt3(); 834 } 835 } 836 if(_configinfo.pSRateConvBuffer) { 837 if(DevHelp_VMFree(_configinfo.pSRateConvBuffer) != 0) { 838 DebugInt3(); 839 } 840 } 841 if(pahw) { 842 if (ulStreamState == STREAM_STREAMING) 843 pahw->Stop(StreamId); 844 845 pahw->Close(StreamId); 846 StreamId = 0; 847 } 848 } 849 //****************************************************************************** 850 //****************************************************************************** 851
Note:
See TracChangeset
for help on using the changeset viewer.