Changed how list of loadable MCI drivers is obtained.
[wine] / multimedia / msvideo.c
1 /*
2  * Copyright 1998 Marcus Meissner
3  */
4 #include <stdio.h>
5 #include <strings.h>
6
7 #include "winbase.h"
8 #include "winuser.h"
9 #include "wingdi.h"
10 #include "vfw.h"
11 #include "wine/winestring.h"
12 #include "driver.h"
13 #include "debug.h"
14
15 /****************************************************************************
16  *              VideoForWindowsVersion          [MSVFW.2][MSVIDEO.2]
17  * Returns the version in major.minor form.
18  * In Windows95 this returns 0x040003b6 (4.950)
19  */
20 DWORD WINAPI
21 VideoForWindowsVersion(void) {
22         return 0x040003B6; /* 4.950 */
23 }
24
25 /* system.ini: [drivers] */
26
27 /**************************************************************************
28  *              ICInfo                          [MSVFW.33]
29  * Get information about an installable compressor. Return TRUE if there
30  * is one.
31  */
32 BOOL WINAPI
33 ICInfo(
34         DWORD fccType,          /* [in] type of compressor ('vidc') */
35         DWORD fccHandler,       /* [in] <n>th compressor */
36         ICINFO *lpicinfo        /* [out] information about compressor */
37 ) {
38         char    type[5],buf[2000];
39
40         memcpy(type,&fccType,4);type[4]=0;
41         TRACE(msvideo,"(%s,%ld,%p).\n",type,fccHandler,lpicinfo);
42         /* does OpenDriver/CloseDriver */
43         lpicinfo->dwSize = sizeof(ICINFO);
44         lpicinfo->fccType = fccType;
45         lpicinfo->dwFlags = 0;
46         if (GetPrivateProfileStringA("drivers32",NULL,NULL,buf,2000,"system.ini")) {
47                 char *s = buf;
48                 while (*s) {
49                         if (!lstrncmpiA(type,s,4)) {
50                                 if(!fccHandler--) {
51                                         lpicinfo->fccHandler = mmioStringToFOURCCA(s+5,0);
52                                         return TRUE;
53                                 }
54                         }
55                         s=s+lstrlenA(s)+1; /* either next char or \0 */
56                 }
57         }
58         return FALSE;
59 }
60
61 /**************************************************************************
62  *              ICOpen                          [MSVFW.37]
63  * Opens an installable compressor. Return special handle.
64  */
65 HIC WINAPI
66 ICOpen(DWORD fccType,DWORD fccHandler,UINT wMode) {
67         char            type[5],handler[5],codecname[20];
68         ICOPEN          icopen;
69         HDRVR           hdrv;
70         WINE_HIC        *whic;
71
72         memcpy(type,&fccType,4);type[4]=0;
73         memcpy(handler,&fccHandler,4);handler[4]=0;
74         TRACE(msvideo,"(%s,%s,0x%08lx)\n",type,handler,(DWORD)wMode);
75         sprintf(codecname,"%s.%s",type,handler);
76
77         /* Well, lParam2 is in fact a LPVIDEO_OPEN_PARMS, but it has the 
78          * same layout as ICOPEN
79          */
80         icopen.fccType          = fccType;
81         icopen.fccHandler       = fccHandler;
82         icopen.dwSize           = sizeof(ICOPEN);
83         icopen.dwFlags          = wMode;
84         /* FIXME: do we need to fill out the rest too? */
85         hdrv=OpenDriverA(codecname,"drivers32",(LPARAM)&icopen);
86         if (!hdrv) {
87             if (!strcasecmp(type,"vids")) {
88                 sprintf(codecname,"vidc.%s",handler);
89                 fccType = mmioFOURCC('v','i','d','c');
90             }
91             hdrv=OpenDriverA(codecname,"drivers32",(LPARAM)&icopen);
92             if (!hdrv)
93                     return 0;
94         }
95         whic = HeapAlloc(GetProcessHeap(),0,sizeof(WINE_HIC));
96         whic->hdrv      = hdrv;
97         whic->driverproc= NULL;
98         whic->private   = ICSendMessage((HIC)whic,DRV_OPEN,0,(LPARAM)&icopen);
99         return (HIC)whic;
100 }
101 HIC VFWAPI ICOpenFunction(DWORD fccType, DWORD fccHandler, UINT wMode,
102 FARPROC lpfnHandler) {
103         char            type[5],handler[5];
104         HIC             hic;
105         WINE_HIC        *whic;
106
107         memcpy(type,&fccType,4);type[4]=0;
108         memcpy(handler,&fccHandler,4);handler[4]=0;
109         FIXME(msvideo,"(%s,%s,%d,%p), stub!\n",type,handler,wMode,lpfnHandler);
110         hic = ICOpen(fccType,fccHandler,wMode);
111         if (!hic)
112                 return hic;
113         whic = (WINE_HIC*)hic;
114         whic->driverproc = lpfnHandler;
115         return hic;
116 }
117
118
119 LRESULT WINAPI
120 ICGetInfo(HIC hic,ICINFO *picinfo,DWORD cb) {
121         LRESULT         ret;
122
123         TRACE(msvideo,"(0x%08lx,%p,%ld)\n",(DWORD)hic,picinfo,cb);
124         ret = ICSendMessage(hic,ICM_GETINFO,(DWORD)picinfo,cb);
125         TRACE(msvideo," -> 0x%08lx\n",ret);
126         return ret;
127 }
128
129 HIC  VFWAPI
130 ICLocate(
131         DWORD fccType, DWORD fccHandler, LPBITMAPINFOHEADER lpbiIn,
132         LPBITMAPINFOHEADER lpbiOut, WORD wMode
133 ) {
134         char    type[5],handler[5];
135         HIC     hic;
136         DWORD   querymsg;
137
138         switch (wMode) {
139         case ICMODE_FASTCOMPRESS:
140         case ICMODE_COMPRESS: 
141                 querymsg = ICM_COMPRESS_QUERY;
142                 break;
143         case ICMODE_DECOMPRESS:
144         case ICMODE_FASTDECOMPRESS:
145                 querymsg = ICM_DECOMPRESS_QUERY;
146                 break;
147         case ICMODE_DRAW:
148                 querymsg = ICM_DRAW_QUERY;
149                 break;
150         default:
151                 FIXME(msvideo,"Unknown mode (%d)\n",wMode);
152                 return 0;
153         }
154
155         /* Easy case: handler/type match, we just fire a query and return */
156         hic = ICOpen(fccType,fccHandler,wMode);
157         if (hic) {
158                 if (!ICSendMessage(hic,querymsg,(DWORD)lpbiIn,(DWORD)lpbiOut))
159                         return hic;
160                 ICClose(hic);
161         }
162         type[4]='\0';memcpy(type,&fccType,4);
163         handler[4]='\0';memcpy(handler,&fccHandler,4);
164         if (fccType==streamtypeVIDEO) {
165                 hic = ICLocate(ICTYPE_VIDEO,fccHandler,lpbiIn,lpbiOut,wMode);
166                 if (hic)
167                         return hic;
168         }
169         FIXME(msvideo,"(%s,%s,%p,%p,0x%04x),unhandled!\n",type,handler,lpbiIn,lpbiOut,wMode);
170         return 0;
171 }
172
173 HIC VFWAPI ICGetDisplayFormat(
174         HIC hic,LPBITMAPINFOHEADER lpbiIn,LPBITMAPINFOHEADER lpbiOut,
175         INT depth,INT dx,INT dy
176 ) {
177         HIC     tmphic = hic; 
178         LRESULT lres;
179
180         FIXME(msvideo,"(0x%08lx,%p,%p,%d,%d,%d),stub!\n",(DWORD)hic,lpbiIn,lpbiOut,depth,dx,dy);
181         if (!tmphic) {
182                 tmphic=ICLocate(ICTYPE_VIDEO,0,lpbiIn,NULL,ICMODE_DECOMPRESS);
183                 if (!tmphic)
184                         return tmphic;
185         }
186         if ((dy == lpbiIn->biHeight) || (dx == lpbiIn->biWidth))
187                 dy = dx = 0; /* no resize needed */
188         /* Can we decompress it ? */
189         lres = ICDecompressQuery(tmphic,lpbiIn,NULL);
190         if (lres)
191                 goto errout; /* no, sorry */
192         ICDecompressGetFormat(hic,lpbiIn,lpbiOut);
193         *lpbiOut=*lpbiIn;
194         lpbiOut->biCompression = 0;
195         lpbiOut->biSize = sizeof(*lpbiOut);
196         if (!depth) {
197                 HDC     hdc;
198
199                 hdc = GetDC(0);
200                 depth = GetDeviceCaps(hdc,12)*GetDeviceCaps(hdc,14);
201                 ReleaseDC(0,hdc);
202                 if (depth==15)  depth = 16;
203                 if (depth<8)    depth =  8;
204                 /* more constraints and tests */
205         }
206         if (lpbiIn->biBitCount == 8)
207                 depth = 8;
208         
209         return hic;
210 errout:
211         if (hic!=tmphic)
212                 ICClose(tmphic);
213         return 0;
214 }
215
216 DWORD VFWAPIV
217 ICCompress(
218         HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiOutput,LPVOID lpData,
219         LPBITMAPINFOHEADER lpbiInput,LPVOID lpBits,LPDWORD lpckid,
220         LPDWORD lpdwFlags,LONG lFrameNum,DWORD dwFrameSize,DWORD dwQuality,
221         LPBITMAPINFOHEADER lpbiPrev,LPVOID lpPrev
222 ) {
223         ICCOMPRESS      iccmp;
224
225         iccmp.dwFlags           = dwFlags;
226
227         iccmp.lpbiOutput        = lpbiOutput;
228         iccmp.lpOutput          = lpData;
229         iccmp.lpbiInput         = lpbiInput;
230         iccmp.lpInput           = lpBits;
231
232         iccmp.lpckid            = lpckid;
233         iccmp.lpdwFlags         = lpdwFlags;
234         iccmp.lFrameNum         = lFrameNum;
235         iccmp.dwFrameSize       = dwFrameSize;
236         iccmp.dwQuality         = dwQuality;
237         iccmp.lpbiPrev          = lpbiPrev;
238         iccmp.lpPrev            = lpPrev;
239         return ICSendMessage(hic,ICM_COMPRESS,(LPARAM)&iccmp,sizeof(iccmp));
240 }
241
242 DWORD VFWAPIV 
243 ICDecompress(HIC hic,DWORD dwFlags,LPBITMAPINFOHEADER lpbiFormat,LPVOID lpData,LPBITMAPINFOHEADER  lpbi,LPVOID lpBits) {
244         ICDECOMPRESS    icd;
245
246         icd.dwFlags     = dwFlags;
247         icd.lpbiInput   = lpbiFormat;
248         icd.lpInput     = lpData;
249
250         icd.lpbiOutput  = lpbi;
251         icd.lpOutput    = lpBits;
252         icd.ckid        = 0;
253         return ICSendMessage(hic,ICM_DECOMPRESS,(LPARAM)&icd,sizeof(icd));
254 }
255
256 LRESULT VFWAPI
257 ICSendMessage(HIC hic,UINT msg,DWORD lParam1,DWORD lParam2) {
258         LRESULT         ret;
259         WINE_HIC        *whic = (WINE_HIC*)hic;
260
261 #define XX(x) case x: TRACE(msvideo,"(0x%08lx,"#x",0x%08lx,0x%08lx)\n",(DWORD)hic,lParam1,lParam2);break;
262
263         switch (msg) {
264         XX(ICM_ABOUT)
265         XX(ICM_GETINFO)
266         XX(ICM_COMPRESS_FRAMES_INFO)
267         XX(ICM_COMPRESS_GET_FORMAT)
268         XX(ICM_COMPRESS_GET_SIZE)
269         XX(ICM_COMPRESS_QUERY)
270         XX(ICM_COMPRESS_BEGIN)
271         XX(ICM_COMPRESS)
272         XX(ICM_COMPRESS_END)
273         XX(ICM_DECOMPRESS_GET_FORMAT)
274         XX(ICM_DECOMPRESS_QUERY)
275         XX(ICM_DECOMPRESS_BEGIN)
276         XX(ICM_DECOMPRESS)
277         XX(ICM_DECOMPRESS_END)
278         XX(ICM_DECOMPRESS_SET_PALETTE)
279         XX(ICM_DECOMPRESS_GET_PALETTE)
280         XX(ICM_DRAW_QUERY)
281         XX(ICM_DRAW_BEGIN)
282         XX(ICM_DRAW_GET_PALETTE)
283         XX(ICM_DRAW_START)
284         XX(ICM_DRAW_STOP)
285         XX(ICM_DRAW_END)
286         XX(ICM_DRAW_GETTIME)
287         XX(ICM_DRAW)
288         XX(ICM_DRAW_WINDOW)
289         XX(ICM_DRAW_SETTIME)
290         XX(ICM_DRAW_REALIZE)
291         XX(ICM_DRAW_FLUSH)
292         XX(ICM_DRAW_RENDERBUFFER)
293         XX(ICM_DRAW_START_PLAY)
294         XX(ICM_DRAW_STOP_PLAY)
295         XX(ICM_DRAW_SUGGESTFORMAT)
296         XX(ICM_DRAW_CHANGEPALETTE)
297         XX(ICM_GETBUFFERSWANTED)
298         XX(ICM_GETDEFAULTKEYFRAMERATE)
299         XX(ICM_DECOMPRESSEX_BEGIN)
300         XX(ICM_DECOMPRESSEX_QUERY)
301         XX(ICM_DECOMPRESSEX)
302         XX(ICM_DECOMPRESSEX_END)
303         XX(ICM_SET_STATUS_PROC)
304         default:
305                 FIXME(msvideo,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx)\n",(DWORD)hic,(DWORD)msg,lParam1,lParam2);
306         }
307 #if 0
308         if (whic->driverproc) {
309                 FIXME(msvideo,"(0x%08lx,0x%08lx,0x%08lx,0x%08lx), calling %p\n",(DWORD)hic,(DWORD)msg,lParam1,lParam2,whic->driverproc);
310                 ret = whic->driverproc(whic->hdrv,1,msg,lParam1,lParam2);
311         } else
312 #endif
313                 ret = SendDriverMessage(whic->hdrv,msg,lParam1,lParam2);
314         TRACE(msvideo," -> 0x%08lx\n",ret);
315         return ret;
316 }
317
318 DWORD   VFWAPIV ICDrawBegin(
319         HIC                     hic,
320         DWORD                   dwFlags,/* flags */
321         HPALETTE                hpal,   /* palette to draw with */
322         HWND                    hwnd,   /* window to draw to */
323         HDC                     hdc,    /* HDC to draw to */
324         INT                     xDst,   /* destination rectangle */
325         INT                     yDst,
326         INT                     dxDst,
327         INT                     dyDst,
328         LPBITMAPINFOHEADER      lpbi,   /* format of frame to draw */
329         INT                     xSrc,   /* source rectangle */
330         INT                     ySrc,
331         INT                     dxSrc,
332         INT                     dySrc,
333         DWORD                   dwRate, /* frames/second = (dwRate/dwScale) */
334         DWORD                   dwScale) {
335         ICDRAWBEGIN     icdb;
336
337         icdb.dwFlags = dwFlags;
338         icdb.hpal = hpal;
339         icdb.hwnd = hwnd;
340         icdb.hdc = hdc;
341         icdb.xDst = xDst;
342         icdb.yDst = yDst;
343         icdb.dxDst = dxDst;
344         icdb.dyDst = dyDst;
345         icdb.lpbi = lpbi;
346         icdb.xSrc = xSrc;
347         icdb.ySrc = ySrc;
348         icdb.dxSrc = dxSrc;
349         icdb.dySrc = dySrc;
350         icdb.dwRate = dwRate;
351         icdb.dwScale = dwScale;
352         return ICSendMessage(hic,ICM_DRAW_BEGIN,(LPARAM)&icdb,sizeof(icdb));
353 }
354
355 DWORD VFWAPIV ICDraw(
356         HIC hic,DWORD dwFlags,LPVOID lpFormat,LPVOID lpData,DWORD cbData,
357         LONG lTime
358 ) {
359         ICDRAW  icd;
360
361         icd.dwFlags = dwFlags;
362         icd.lpFormat = lpFormat;
363         icd.lpData = lpData;
364         icd.cbData = cbData;
365         icd.lTime = lTime;
366         return ICSendMessage(hic,ICM_DRAW,(LPARAM)&icd,sizeof(icd));
367 }
368
369 LRESULT WINAPI ICClose(HIC hic) {
370         WINE_HIC        *whic = (WINE_HIC*)hic;
371         TRACE(msvideo,"(%d).\n",hic);
372         /* FIXME: correct? */
373         CloseDriver(whic->hdrv,0,0);
374         HeapFree(GetProcessHeap(),0,whic);
375         return 0;
376 }
377
378 HANDLE /* HDRAWDIB */ WINAPI
379 DrawDibOpen( void ) {
380         FIXME(msvideo,"stub!\n");
381         return 0xdead;
382 }
383
384 BOOL VFWAPI DrawDibBegin(HANDLE /*HDRAWDIB*/ hdd,
385                                     HDC      hdc,
386                                     INT      dxDst,
387                                     INT      dyDst,
388                                     LPBITMAPINFOHEADER lpbi,
389                                     INT      dxSrc,
390                                     INT      dySrc,
391                                     UINT     wFlags) {
392         FIXME(msvideo,"(%d,0x%lx,%d,%d,%p,%d,%d,0x%08lx), stub!\n",
393                 hdd,(DWORD)hdc,dxDst,dyDst,lpbi,dxSrc,dySrc,(DWORD)wFlags
394         );
395         return TRUE;
396 }
397
398
399 BOOL VFWAPI
400 DrawDibSetPalette(HANDLE /*HDRAWDIB*/ hdd, HPALETTE hpal) {
401         FIXME(msvideo,"(%d,%d),stub!\n",hdd,hpal);
402         return TRUE;
403 }
404
405 UINT VFWAPI DrawDibRealize(HANDLE /*HDRAWDIB*/ hdd, HDC hdc, BOOL fBackground) {
406         FIXME(msvideo,"(0x%08lx,0x%08lx,%d),stub!\n",(DWORD)hdd,(DWORD)hdc,fBackground);
407         return 0;
408 }
409
410
411 HWND VFWAPIV MCIWndCreate (HWND hwndParent, HINSTANCE hInstance,
412                       DWORD dwStyle,LPVOID szFile)
413 {       FIXME(msvideo,"%x %x %lx %p\n",hwndParent, hInstance, dwStyle, szFile);
414         return 0;
415 }
416 HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
417                       DWORD dwStyle,LPCSTR szFile)
418 {       FIXME(msvideo,"%x %x %lx %s\n",hwndParent, hInstance, dwStyle, szFile);
419         return 0;
420 }
421 HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
422                       DWORD dwStyle,LPCWSTR szFile)
423 {       FIXME(msvideo,"%x %x %lx %s\n",hwndParent, hInstance, dwStyle, debugstr_w(szFile));
424         return 0;
425 }