LRESULT Frameserver::SessionAudio(LPARAM lParam, WPARAM lStart) { FrameserverSession *fs = SessionLookup(lParam); if (!fs) return VDSRVERR_BADSESSION; LONG lCount = *(LONG *)fs->arena; LONG cbBuffer = *(LONG *)(fs->arena+4); if (cbBuffer > fs->arena_size - 8) cbBuffer = fs->arena_size - 8; VDDEBUG("[session %08lx] VDSRVM_REQ_AUDIO(sample %ld, count %d, cbBuffer %ld)\n", lParam, lCount, lStart, cbBuffer); // Do not return an error on an attempt to read beyond the end of // the audio stream -- this causes Panasonic to error. if (lStart >= lAudioSamples) { memset(fs->arena, 0, 8); return VDSRVERR_OK; } if (lStart+lCount > lAudioSamples) lCount = lAudioSamples; // Read subsets. long lTotalBytes = 0, lTotalSamples = 0; uint32 lActualBytes, lActualSamples = 1; char *pDest = (char *)(fs->arena + 8); try { while(lCount>0 && lActualSamples>0) { sint64 start, len; // Translate range. start = audioset.lookupRange(lStart, len); if (len > lCount) len = lCount; if (start < aSrc->getStart()) { start = aSrc->getStart(); len = 1; } if (start >= aSrc->getEnd()) { start = aSrc->getEnd() - 1; len = 1; } // Attempt read. switch(aSrc->read(start, len, pDest, cbBuffer, &lActualBytes, &lActualSamples)) { case AVIERR_OK: break; case AVIERR_BUFFERTOOSMALL: if (!lTotalSamples) return VDSRVERR_TOOBIG; goto out_of_space; default: return VDSRVERR_FAILED; } lCount -= lActualSamples; lStart += lActualSamples; cbBuffer -= lActualBytes; pDest += lActualBytes; lTotalSamples += lActualSamples; lTotalBytes += lActualBytes; } out_of_space: ; } catch(const MyError&) { return VDSRVERR_FAILED; } *(LONG *)(fs->arena + 0) = lTotalBytes; *(LONG *)(fs->arena + 4) = lTotalSamples; return VDSRVERR_OK; }