Added mappings for a few messages.
[wine] / dlls / winmm / mciavi / mmoutput.c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2
3 /*
4  * Digital video MCI Wine Driver
5  *
6  * Copyright 1999, 2000 Eric POUECH
7  */
8
9 #include "private_mciavi.h"
10 #include "debugtools.h"
11
12 DEFAULT_DEBUG_CHANNEL(mciavi);
13
14 static BOOL MCIAVI_GetInfoAudio(WINE_MCIAVI* wma, const MMCKINFO* mmckList)
15 {
16     MMCKINFO    mmckInfo;
17     
18     mmckInfo.ckid = ckidSTREAMHEADER;
19     if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
20         WARN("Can't find 'strh' chunk\n");
21         return FALSE;
22     }
23     
24     mmioRead(wma->hFile, (LPSTR)&wma->ash_audio, sizeof(wma->ash_audio));
25     
26     TRACE("ash.fccType='%c%c%c%c'\n",           LOBYTE(LOWORD(wma->ash_audio.fccType)), 
27                                                 HIBYTE(LOWORD(wma->ash_audio.fccType)), 
28                                                 LOBYTE(HIWORD(wma->ash_audio.fccType)), 
29                                                 HIBYTE(HIWORD(wma->ash_audio.fccType)));
30     TRACE("ash.fccHandler='%c%c%c%c'\n",        LOBYTE(LOWORD(wma->ash_audio.fccHandler)), 
31                                                 HIBYTE(LOWORD(wma->ash_audio.fccHandler)), 
32                                                 LOBYTE(HIWORD(wma->ash_audio.fccHandler)), 
33                                                 HIBYTE(HIWORD(wma->ash_audio.fccHandler)));
34     TRACE("ash.dwFlags=%ld\n",                  wma->ash_audio.dwFlags);
35     TRACE("ash.wPriority=%d\n",                 wma->ash_audio.wPriority);
36     TRACE("ash.wLanguage=%d\n",                 wma->ash_audio.wLanguage);
37     TRACE("ash.dwInitialFrames=%ld\n",          wma->ash_audio.dwInitialFrames);
38     TRACE("ash.dwScale=%ld\n",                  wma->ash_audio.dwScale);
39     TRACE("ash.dwRate=%ld\n",                   wma->ash_audio.dwRate);
40     TRACE("ash.dwStart=%ld\n",                  wma->ash_audio.dwStart);
41     TRACE("ash.dwLength=%ld\n",                 wma->ash_audio.dwLength);
42     TRACE("ash.dwSuggestedBufferSize=%ld\n",    wma->ash_audio.dwSuggestedBufferSize);
43     TRACE("ash.dwQuality=%ld\n",                wma->ash_audio.dwQuality);
44     TRACE("ash.dwSampleSize=%ld\n",             wma->ash_audio.dwSampleSize);
45     TRACE("ash.rcFrame=(%d,%d,%d,%d)\n",        wma->ash_audio.rcFrame.top, wma->ash_audio.rcFrame.left, 
46           wma->ash_audio.rcFrame.bottom, wma->ash_audio.rcFrame.right);
47     
48     mmioAscend(wma->hFile, &mmckInfo, 0);
49     
50     mmckInfo.ckid = ckidSTREAMFORMAT;
51     if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
52         WARN("Can't find 'strh' chunk\n");
53         return FALSE;
54     }
55     if (mmckInfo.cksize < sizeof(WAVEFORMAT)) {
56         WARN("Size of strf chunk (%ld) < audio format struct\n", mmckInfo.cksize);
57         return FALSE;
58     }
59     wma->lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
60     if (!wma->lpWaveFormat) {
61         WARN("Can't alloc WaveFormat\n");
62         return FALSE;
63     }
64     
65     mmioRead(wma->hFile, (LPSTR)wma->lpWaveFormat, mmckInfo.cksize);
66     
67     TRACE("waveFormat.wFormatTag=%d\n",         wma->lpWaveFormat->wFormatTag);
68     TRACE("waveFormat.nChannels=%d\n",          wma->lpWaveFormat->nChannels);
69     TRACE("waveFormat.nSamplesPerSec=%ld\n",    wma->lpWaveFormat->nSamplesPerSec);
70     TRACE("waveFormat.nAvgBytesPerSec=%ld\n",   wma->lpWaveFormat->nAvgBytesPerSec);
71     TRACE("waveFormat.nBlockAlign=%d\n",        wma->lpWaveFormat->nBlockAlign);
72     TRACE("waveFormat.wBitsPerSample=%d\n",     wma->lpWaveFormat->wBitsPerSample);
73     if (mmckInfo.cksize >= sizeof(WAVEFORMATEX))
74         TRACE("waveFormat.cbSize=%d\n",                 wma->lpWaveFormat->cbSize);
75     
76     mmioAscend(wma->hFile, &mmckInfo, 0);
77     
78     return TRUE;
79 }
80
81 static BOOL MCIAVI_GetInfoVideo(WINE_MCIAVI* wma, const MMCKINFO* mmckList)
82 {
83     MMCKINFO    mmckInfo;
84     
85     mmckInfo.ckid = ckidSTREAMHEADER;
86     if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
87         WARN("Can't find 'strh' chunk\n");
88         return FALSE;
89     }
90     
91     mmioRead(wma->hFile, (LPSTR)&wma->ash_video, sizeof(wma->ash_video));
92     
93     TRACE("ash.fccType='%c%c%c%c'\n",           LOBYTE(LOWORD(wma->ash_video.fccType)), 
94                                                 HIBYTE(LOWORD(wma->ash_video.fccType)), 
95                                                 LOBYTE(HIWORD(wma->ash_video.fccType)), 
96                                                 HIBYTE(HIWORD(wma->ash_video.fccType)));
97     TRACE("ash.fccHandler='%c%c%c%c'\n",        LOBYTE(LOWORD(wma->ash_video.fccHandler)), 
98                                                 HIBYTE(LOWORD(wma->ash_video.fccHandler)), 
99                                                 LOBYTE(HIWORD(wma->ash_video.fccHandler)), 
100                                                 HIBYTE(HIWORD(wma->ash_video.fccHandler)));
101     TRACE("ash.dwFlags=%ld\n",                  wma->ash_video.dwFlags);
102     TRACE("ash.wPriority=%d\n",                 wma->ash_video.wPriority);
103     TRACE("ash.wLanguage=%d\n",                 wma->ash_video.wLanguage);
104     TRACE("ash.dwInitialFrames=%ld\n",          wma->ash_video.dwInitialFrames);
105     TRACE("ash.dwScale=%ld\n",                  wma->ash_video.dwScale);
106     TRACE("ash.dwRate=%ld\n",                   wma->ash_video.dwRate);
107     TRACE("ash.dwStart=%ld\n",                  wma->ash_video.dwStart);
108     TRACE("ash.dwLength=%ld\n",                 wma->ash_video.dwLength);
109     TRACE("ash.dwSuggestedBufferSize=%ld\n",    wma->ash_video.dwSuggestedBufferSize);
110     TRACE("ash.dwQuality=%ld\n",                wma->ash_video.dwQuality);
111     TRACE("ash.dwSampleSize=%ld\n",             wma->ash_video.dwSampleSize);
112     TRACE("ash.rcFrame=(%d,%d,%d,%d)\n",        wma->ash_video.rcFrame.top, wma->ash_video.rcFrame.left, 
113           wma->ash_video.rcFrame.bottom, wma->ash_video.rcFrame.right);
114     
115     mmioAscend(wma->hFile, &mmckInfo, 0);
116     
117     mmckInfo.ckid = ckidSTREAMFORMAT;
118     if (mmioDescend(wma->hFile, &mmckInfo, mmckList, MMIO_FINDCHUNK) != 0) {
119         WARN("Can't find 'strh' chunk\n");
120         return FALSE;
121     }
122     
123     wma->inbih = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);
124     if (!wma->inbih) {
125         WARN("Can't alloc input BIH\n");
126         return FALSE;
127     }
128     
129     mmioRead(wma->hFile, (LPSTR)wma->inbih, mmckInfo.cksize);
130     
131     TRACE("bih.biSize=%ld\n",           wma->inbih->biSize);
132     TRACE("bih.biWidth=%ld\n",          wma->inbih->biWidth);
133     TRACE("bih.biHeight=%ld\n",         wma->inbih->biHeight);
134     TRACE("bih.biPlanes=%d\n",          wma->inbih->biPlanes);
135     TRACE("bih.biBitCount=%d\n",        wma->inbih->biBitCount);
136     TRACE("bih.biCompression=%lx\n",    wma->inbih->biCompression);
137     TRACE("bih.biSizeImage=%ld\n",      wma->inbih->biSizeImage);
138     TRACE("bih.biXPelsPerMeter=%ld\n",  wma->inbih->biXPelsPerMeter);
139     TRACE("bih.biYPelsPerMeter=%ld\n",  wma->inbih->biYPelsPerMeter);
140     TRACE("bih.biClrUsed=%ld\n",        wma->inbih->biClrUsed);
141     TRACE("bih.biClrImportant=%ld\n",   wma->inbih->biClrImportant);
142     
143     mmioAscend(wma->hFile, &mmckInfo, 0);
144     
145     return TRUE;
146 }
147
148 struct AviListBuild {
149     DWORD       numVideoFrames;
150     DWORD       numAudioAllocated;
151     DWORD       numAudioBlocks;
152     DWORD       inVideoSize;
153     DWORD       inAudioSize;
154 };
155
156 static BOOL     MCIAVI_AddFrame(WINE_MCIAVI* wma, LPMMCKINFO mmck, 
157                                 struct AviListBuild* alb)
158 {
159     if (mmck->ckid == ckidAVIPADDING) return TRUE;
160     
161     switch (TWOCCFromFOURCC(mmck->ckid)) {
162     case cktypeDIBbits:
163     case cktypeDIBcompressed:
164     case cktypePALchange:
165         TRACE("Adding video frame[%ld]: %ld bytes\n", 
166               alb->numVideoFrames, mmck->cksize);
167         if (alb->numVideoFrames < wma->dwPlayableVideoFrames) {
168             wma->lpVideoIndex[alb->numVideoFrames].dwOffset = mmck->dwDataOffset;
169             wma->lpVideoIndex[alb->numVideoFrames].dwSize = mmck->cksize;
170             if (alb->inVideoSize < mmck->cksize)
171                 alb->inVideoSize = mmck->cksize;
172             alb->numVideoFrames++;
173         } else {
174             WARN("Too many video frames\n");
175         }
176         break;
177     case cktypeWAVEbytes:
178         TRACE("Adding audio frame[%ld]: %ld bytes\n", 
179               alb->numAudioBlocks, mmck->cksize);
180         if (wma->lpWaveFormat) {
181             if (alb->numAudioBlocks >= alb->numAudioAllocated) {
182                 alb->numAudioAllocated += 32;
183                 wma->lpAudioIndex = HeapReAlloc(GetProcessHeap(), 0, 
184                                                 wma->lpAudioIndex, 
185                                                 alb->numAudioAllocated * sizeof(struct MMIOPos));
186                 if (!wma->lpAudioIndex) return FALSE;
187             }
188             wma->lpAudioIndex[alb->numAudioBlocks].dwOffset = mmck->dwDataOffset;
189             wma->lpAudioIndex[alb->numAudioBlocks].dwSize = mmck->cksize;
190             if (alb->inAudioSize < mmck->cksize)
191                 alb->inAudioSize = mmck->cksize;
192             alb->numAudioBlocks++;
193         } else {
194             WARN("Wave chunk without wave format... discarding\n");
195         }
196         break;
197     default:
198         WARN("Unknown frame type %04x\n", TWOCCFromFOURCC(mmck->ckid));
199         break;
200     }
201     return TRUE;
202 }
203
204 BOOL MCIAVI_GetInfo(WINE_MCIAVI* wma)
205 {
206     MMCKINFO            ckMainRIFF;
207     MMCKINFO            mmckHead;
208     MMCKINFO            mmckList;
209     MMCKINFO            mmckInfo;
210     struct AviListBuild alb;
211     
212     if (mmioDescend(wma->hFile, &ckMainRIFF, NULL, 0) != 0) {
213         WARN("Can't find 'RIFF' chunk\n");
214         return FALSE;
215     }
216     
217     if ((ckMainRIFF.ckid != FOURCC_RIFF) || (ckMainRIFF.fccType != formtypeAVI)) {
218         WARN("Can't find 'AVI ' chunk\n");
219         return FALSE;
220     }
221     
222     mmckHead.fccType = listtypeAVIHEADER;
223     if (mmioDescend(wma->hFile, &mmckHead, &ckMainRIFF, MMIO_FINDLIST) != 0) {
224         WARN("Can't find 'hdrl' list\n");
225         return FALSE;
226     }
227     
228     mmckInfo.ckid = ckidAVIMAINHDR;
229     if (mmioDescend(wma->hFile, &mmckInfo, &mmckHead, MMIO_FINDCHUNK) != 0) {
230         WARN("Can't find 'avih' chunk\n");
231         return FALSE;
232     }
233     
234     mmioRead(wma->hFile, (LPSTR)&wma->mah, sizeof(wma->mah));
235     
236     TRACE("mah.dwMicroSecPerFrame=%ld\n",       wma->mah.dwMicroSecPerFrame);
237     TRACE("mah.dwMaxBytesPerSec=%ld\n",         wma->mah.dwMaxBytesPerSec);
238     TRACE("mah.dwPaddingGranularity=%ld\n",     wma->mah.dwPaddingGranularity);
239     TRACE("mah.dwFlags=%ld\n",                  wma->mah.dwFlags);
240     TRACE("mah.dwTotalFrames=%ld\n",            wma->mah.dwTotalFrames);
241     TRACE("mah.dwInitialFrames=%ld\n",          wma->mah.dwInitialFrames);
242     TRACE("mah.dwStreams=%ld\n",                wma->mah.dwStreams);
243     TRACE("mah.dwSuggestedBufferSize=%ld\n",    wma->mah.dwSuggestedBufferSize);
244     TRACE("mah.dwWidth=%ld\n",                  wma->mah.dwWidth);
245     TRACE("mah.dwHeight=%ld\n",                 wma->mah.dwHeight);
246     
247     mmioAscend(wma->hFile, &mmckInfo, 0);
248     
249     mmckList.fccType = listtypeSTREAMHEADER;
250     if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) != 0) {
251         WARN("Can't find 'strl' list\n");
252         return FALSE;
253     }
254     
255     if (!MCIAVI_GetInfoVideo(wma, &mmckList)) {
256         return FALSE;
257     }
258     
259     mmioAscend(wma->hFile, &mmckList, 0);
260     
261     mmckList.fccType = listtypeSTREAMHEADER;
262     if (mmioDescend(wma->hFile, &mmckList, &mmckHead, MMIO_FINDLIST) == 0) {
263         if (!MCIAVI_GetInfoAudio(wma, &mmckList)) {
264             return FALSE;
265         }
266         mmioAscend(wma->hFile, &mmckList, 0);
267     }
268     
269     mmioAscend(wma->hFile, &mmckHead, 0);
270     
271     /* no need to read optional JUNK chunk */
272     
273     mmckList.fccType = listtypeAVIMOVIE;
274     if (mmioDescend(wma->hFile, &mmckList, &ckMainRIFF, MMIO_FINDLIST) != 0) {
275         WARN("Can't find 'movi' list\n");
276         return FALSE;
277     }
278     
279     wma->dwPlayableVideoFrames = wma->mah.dwTotalFrames;
280     wma->lpVideoIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
281                                   wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
282     if (!wma->lpVideoIndex) {
283         WARN("Can't alloc video index array\n");
284         return FALSE;
285     }
286     wma->dwPlayableAudioBlocks = 0;
287     wma->lpAudioIndex = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
288                                   wma->dwPlayableVideoFrames * sizeof(struct MMIOPos));
289     if (!wma->lpAudioIndex) {
290         WARN("Can't alloc audio index array\n");
291         return FALSE;
292     }
293     
294     alb.numAudioBlocks = alb.numVideoFrames = 0;
295     alb.inVideoSize = alb.inAudioSize = 0;
296     alb.numAudioAllocated = 0;
297     
298     while (mmioDescend(wma->hFile, &mmckInfo, &mmckList, 0) == 0) {
299         if (mmckInfo.fccType == listtypeAVIRECORD) {    
300             MMCKINFO    tmp;
301             
302             while (mmioDescend(wma->hFile, &tmp, &mmckInfo, 0) == 0) {
303                 MCIAVI_AddFrame(wma, &tmp, &alb);
304                 mmioAscend(wma->hFile, &tmp, 0);
305             }
306         } else {
307             MCIAVI_AddFrame(wma, &mmckInfo, &alb);
308         }
309         
310         mmioAscend(wma->hFile, &mmckInfo, 0);
311     }
312     if (alb.numVideoFrames != wma->dwPlayableVideoFrames) {
313         WARN("Found %ld video frames (/%ld), reducing playable frames\n", 
314              alb.numVideoFrames, wma->dwPlayableVideoFrames);
315         wma->dwPlayableVideoFrames = alb.numVideoFrames;
316     }
317     wma->dwPlayableAudioBlocks = alb.numAudioBlocks;
318     
319     if (alb.inVideoSize > wma->ash_video.dwSuggestedBufferSize) {
320         WARN("inVideoSize=%ld suggestedSize=%ld\n", alb.inVideoSize, wma->ash_video.dwSuggestedBufferSize);
321         wma->ash_video.dwSuggestedBufferSize = alb.inVideoSize;
322     }
323     if (alb.inAudioSize > wma->ash_audio.dwSuggestedBufferSize) {
324         WARN("inAudioSize=%ld suggestedSize=%ld\n", alb.inAudioSize, wma->ash_audio.dwSuggestedBufferSize);
325         wma->ash_audio.dwSuggestedBufferSize = alb.inAudioSize;
326     }
327     
328     wma->indata = HeapAlloc(GetProcessHeap(), 0, wma->ash_video.dwSuggestedBufferSize);
329     if (!wma->indata) {
330         WARN("Can't alloc input buffer\n");
331         return FALSE;
332     }
333     
334     return TRUE;
335 }
336
337 BOOL    MCIAVI_OpenVideo(WINE_MCIAVI* wma)
338 {
339     DWORD       outSize;
340     FOURCC      fcc = wma->ash_video.fccHandler;
341     
342     /* check uncompressed AVI */
343     if ((fcc == mmioFOURCC('D','I','B',' ')) || 
344         (fcc == mmioFOURCC('R','L','E',' '))) {
345         wma->hic = 0;             
346         MCIAVI_DrawFrame(wma);
347         return TRUE;
348     }
349     
350     /* get the right handle */
351     if (fcc == 0) fcc = wma->inbih->biCompression;
352     if (fcc == mmioFOURCC('C','R','A','M')) fcc = mmioFOURCC('M','S','V','C');
353     
354     /* try to get a decompressor for that type */
355     wma->hic = ICLocate(ICTYPE_VIDEO, fcc, wma->inbih, NULL, ICMODE_DECOMPRESS);
356     if (!wma->hic) {
357         WARN("Can't locate codec for the file\n");
358         return FALSE;
359     }
360     
361     outSize = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
362     
363     wma->outbih = HeapAlloc(GetProcessHeap(), 0, outSize);
364     if (!wma->outbih) {
365         WARN("Can't alloc output BIH\n");
366         return FALSE;
367     }
368     if (!ICGetDisplayFormat(wma->hic, wma->inbih, wma->outbih, 0, 0, 0)) {
369         WARN("Can't open decompressor\n");
370         return FALSE;
371     }
372     
373     TRACE("bih.biSize=%ld\n",           wma->outbih->biSize);
374     TRACE("bih.biWidth=%ld\n",          wma->outbih->biWidth);
375     TRACE("bih.biHeight=%ld\n",         wma->outbih->biHeight);
376     TRACE("bih.biPlanes=%d\n",          wma->outbih->biPlanes);
377     TRACE("bih.biBitCount=%d\n",        wma->outbih->biBitCount);
378     TRACE("bih.biCompression=%lx\n",    wma->outbih->biCompression);
379     TRACE("bih.biSizeImage=%ld\n",      wma->outbih->biSizeImage);
380     TRACE("bih.biXPelsPerMeter=%ld\n",  wma->outbih->biXPelsPerMeter);
381     TRACE("bih.biYPelsPerMeter=%ld\n",  wma->outbih->biYPelsPerMeter);
382     TRACE("bih.biClrUsed=%ld\n",        wma->outbih->biClrUsed);
383     TRACE("bih.biClrImportant=%ld\n",   wma->outbih->biClrImportant);
384     
385     wma->outdata = HeapAlloc(GetProcessHeap(), 0, wma->outbih->biSizeImage);
386     if (!wma->outdata) {
387         WARN("Can't alloc output buffer\n");
388         return FALSE;
389     }
390     
391     if (ICSendMessage(wma->hic, ICM_DECOMPRESS_BEGIN, 
392                       (DWORD)wma->inbih, (DWORD)wma->outbih) != ICERR_OK) {
393         WARN("Can't begin decompression\n");
394         return FALSE;
395     }
396     
397     MCIAVI_DrawFrame(wma);
398     
399     return TRUE;
400 }
401
402 static void CALLBACK MCIAVI_waveCallback(HWAVEOUT hwo, UINT uMsg, DWORD dwInstance,  
403                                          DWORD dwParam1, DWORD dwParam2)
404 {
405     WINE_MCIAVI*        wma = (WINE_MCIAVI*)dwInstance;
406     
407     switch (uMsg) {
408     case WOM_OPEN:
409     case WOM_CLOSE:
410         break;
411     case WOM_DONE:
412         InterlockedIncrement(&wma->dwEventCount);
413         TRACE("Returning waveHdr=%lx\n", dwParam1);
414         SetEvent(wma->hEvent);
415         break;
416     default:
417         ERR("Unknown uMsg=%d\n", uMsg);
418     }
419 }
420
421 DWORD MCIAVI_OpenAudio(WINE_MCIAVI* wma, unsigned* nHdr, LPWAVEHDR* pWaveHdr)
422 {
423     DWORD       dwRet;
424     LPWAVEHDR   waveHdr;
425     unsigned    i;
426     
427     dwRet = waveOutOpen(&wma->hWave, WAVE_MAPPER, wma->lpWaveFormat, 
428                         (DWORD)MCIAVI_waveCallback, (DWORD)wma, CALLBACK_FUNCTION);
429     if (dwRet != 0) {
430         TRACE("Can't open low level audio device %ld\n", dwRet);
431         dwRet = MCIERR_DEVICE_OPEN;
432         wma->hWave = 0;
433         goto cleanUp;
434     }
435     
436     /* FIXME: should set up a heuristic to compute the number of wave headers
437      * to be used...
438      */
439     *nHdr = 7;
440     waveHdr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 
441                         *nHdr * (sizeof(WAVEHDR) + wma->ash_audio.dwSuggestedBufferSize));
442     if (!waveHdr) {
443         TRACE("Can't alloc wave headers\n");
444         dwRet = MCIERR_DEVICE_OPEN;
445         goto cleanUp;
446     }
447     
448     for (i = 0; i < *nHdr; i++) {
449         /* other fields are zero:ed on allocation */
450         waveHdr[i].lpData = (char*)waveHdr + 
451             *nHdr * sizeof(WAVEHDR) + i * wma->ash_audio.dwSuggestedBufferSize;
452         waveHdr[i].dwBufferLength = wma->ash_audio.dwSuggestedBufferSize;
453         if (waveOutPrepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR))) {
454             dwRet = MCIERR_INTERNAL;
455             goto cleanUp;
456         }
457     }
458     
459     if (wma->dwCurrVideoFrame != 0 && wma->lpWaveFormat) {
460         FIXME("Should recompute dwCurrAudioBlock, except unsynchronized sound & video\n");
461     }
462     wma->dwCurrAudioBlock = 0;
463     
464     wma->hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
465     wma->dwEventCount = *nHdr - 1;
466     *pWaveHdr = waveHdr;
467  cleanUp:
468     return dwRet;
469 }       
470
471 void MCIAVI_PlayAudioBlocks(WINE_MCIAVI* wma, unsigned nHdr, LPWAVEHDR waveHdr)
472 {
473     TRACE("%ld (ec=%lu)\n", wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, wma->dwEventCount);
474     
475     /* push as many blocks as possible => audio gets priority */
476     while (wma->dwStatus != MCI_MODE_STOP && wma->dwStatus != MCI_MODE_NOT_READY && 
477            wma->dwCurrAudioBlock < wma->dwPlayableAudioBlocks) {
478         unsigned        whidx = wma->dwCurrAudioBlock % nHdr;
479         
480         ResetEvent(wma->hEvent);
481         if (InterlockedDecrement(&wma->dwEventCount) < 0 ||
482             !wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset)
483             break;
484         
485         mmioSeek(wma->hFile, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwOffset, SEEK_SET);
486         mmioRead(wma->hFile, waveHdr[whidx].lpData, wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize);
487         
488         waveHdr[whidx].dwFlags &= ~WHDR_DONE;
489         waveHdr[whidx].dwBufferLength = wma->lpAudioIndex[wma->dwCurrAudioBlock].dwSize;
490         waveOutWrite(wma->hWave, &waveHdr[whidx], sizeof(WAVEHDR));
491         wma->dwCurrAudioBlock++;
492     }
493     InterlockedIncrement(&wma->dwEventCount);
494 }
495
496 LRESULT MCIAVI_PaintFrame(WINE_MCIAVI* wma, HDC hDC)
497 {
498     void*               pBitmapData = NULL;
499     LPBITMAPINFO        pBitmapInfo = NULL;
500     HDC                 hdcMem;
501     HBITMAP             hbmOld;
502     int                 nWidth;
503     int                 nHeight;
504     
505     if (!hDC || !wma->inbih)
506         return TRUE;
507     
508     TRACE("Painting frame %lu\n", wma->dwCurrVideoFrame);
509     
510     if (wma->hic) {
511         pBitmapData = wma->outdata;
512         pBitmapInfo = (LPBITMAPINFO)wma->outbih;
513         
514         nWidth = wma->outbih->biWidth;
515         nHeight = wma->outbih->biHeight;  
516     } else {  
517         pBitmapData = wma->indata;
518         pBitmapInfo = (LPBITMAPINFO)wma->inbih;
519         
520         nWidth = wma->inbih->biWidth;
521         nHeight = wma->inbih->biHeight;  
522     }  
523     
524     if (!wma->hbmFrame) 
525         wma->hbmFrame = CreateCompatibleBitmap(hDC, nWidth, nHeight);
526     
527     SetDIBits(hDC, wma->hbmFrame, 0, nHeight, pBitmapData, pBitmapInfo, DIB_RGB_COLORS); 
528     
529     hdcMem = CreateCompatibleDC(hDC);
530     hbmOld = SelectObject(hdcMem, wma->hbmFrame);
531     
532     BitBlt(hDC, 0, 0, nWidth, nHeight, hdcMem, 0, 0, SRCCOPY);    
533     
534     SelectObject(hdcMem, hbmOld);
535     DeleteDC(hdcMem);
536     return TRUE;
537 }
538
539 LRESULT MCIAVI_DrawFrame(WINE_MCIAVI* wma)
540 {
541     HDC         hDC;
542     
543     TRACE("Drawing frame %lu\n", wma->dwCurrVideoFrame);
544     
545     if (!wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset)
546         return FALSE;
547     
548     EnterCriticalSection(&wma->cs);
549     
550     mmioSeek(wma->hFile, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwOffset, SEEK_SET);
551     mmioRead(wma->hFile, wma->indata, wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize);
552     
553     /* FIXME ? */
554     wma->inbih->biSizeImage = wma->lpVideoIndex[wma->dwCurrVideoFrame].dwSize;
555     
556     if (wma->hic &&
557         ICDecompress(wma->hic, 0, wma->inbih, wma->indata, 
558                      wma->outbih, wma->outdata) != ICERR_OK) {
559         LeaveCriticalSection(&wma->cs);
560         WARN("Decompression error\n");
561         return FALSE;
562     }
563     
564     if (IsWindowVisible(wma->hWnd) && (hDC = GetDC(wma->hWnd)) != 0) {
565         MCIAVI_PaintFrame(wma, hDC);
566         ReleaseDC(wma->hWnd, hDC);
567     }
568     
569     LeaveCriticalSection(&wma->cs);
570     
571     return TRUE;
572 }
573