Moved mciavi32 to the top-level dlls directory.
[wine] / dlls / mciavi32 / info.c
1 /*
2  * Digital video MCI Wine Driver
3  *
4  * Copyright 1999, 2000 Eric POUECH
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <string.h>
22 #include "private_mciavi.h"
23 #include "wine/debug.h"
24 #include "wine/unicode.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
27
28 /**************************************************************************
29  *                              MCIAVI_ConvertFrameToTimeFormat [internal]
30  */
31 DWORD   MCIAVI_ConvertFrameToTimeFormat(WINE_MCIAVI* wma, DWORD val, LPDWORD lpRet)
32 {
33     DWORD          ret = 0;
34
35     switch (wma->dwMciTimeFormat) {
36     case MCI_FORMAT_MILLISECONDS:
37         ret = (val * wma->mah.dwMicroSecPerFrame) / 1000;
38         break;
39     case MCI_FORMAT_FRAMES:
40         ret = val;
41         break;
42     default:
43         WARN("Bad time format %lu!\n", wma->dwMciTimeFormat);
44     }
45     TRACE("val=%lu=0x%08lx [tf=%lu] => ret=%lu\n", val, val, wma->dwMciTimeFormat, ret);
46     *lpRet = 0;
47     return ret;
48 }
49
50 /**************************************************************************
51  *                              MCIAVI_ConvertTimeFormatToFrame [internal]
52  */
53 DWORD   MCIAVI_ConvertTimeFormatToFrame(WINE_MCIAVI* wma, DWORD val)
54 {
55     DWORD       ret = 0;
56
57     switch (wma->dwMciTimeFormat) {
58     case MCI_FORMAT_MILLISECONDS:
59         ret = (val * 1000) / wma->mah.dwMicroSecPerFrame;
60         break;
61     case MCI_FORMAT_FRAMES:
62         ret = val;
63         break;
64     default:
65         WARN("Bad time format %lu!\n", wma->dwMciTimeFormat);
66     }
67     TRACE("val=%lu=0x%08lx [tf=%lu] => ret=%lu\n", val, val, wma->dwMciTimeFormat, ret);
68     return ret;
69 }
70
71 /***************************************************************************
72  *                              MCIAVI_mciGetDevCaps            [internal]
73  */
74 DWORD   MCIAVI_mciGetDevCaps(UINT wDevID, DWORD dwFlags,  LPMCI_GETDEVCAPS_PARMS lpParms)
75 {
76     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
77     DWORD               ret;
78
79     TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
80
81     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
82     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
83
84     EnterCriticalSection(&wma->cs);
85
86     if (dwFlags & MCI_GETDEVCAPS_ITEM) {
87         switch (lpParms->dwItem) {
88         case MCI_GETDEVCAPS_DEVICE_TYPE:
89             TRACE("MCI_GETDEVCAPS_DEVICE_TYPE !\n");
90             lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_DIGITAL_VIDEO, MCI_DEVTYPE_DIGITAL_VIDEO);
91             ret = MCI_RESOURCE_RETURNED;
92             break;
93         case MCI_GETDEVCAPS_HAS_AUDIO:
94             TRACE("MCI_GETDEVCAPS_HAS_AUDIO !\n");
95             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
96             ret = MCI_RESOURCE_RETURNED;
97             break;
98         case MCI_GETDEVCAPS_HAS_VIDEO:
99             TRACE("MCI_GETDEVCAPS_HAS_VIDEO !\n");
100             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
101             ret = MCI_RESOURCE_RETURNED;
102             break;
103         case MCI_GETDEVCAPS_USES_FILES:
104             TRACE("MCI_GETDEVCAPS_USES_FILES !\n");
105             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
106             ret = MCI_RESOURCE_RETURNED;
107             break;
108         case MCI_GETDEVCAPS_COMPOUND_DEVICE:
109             TRACE("MCI_GETDEVCAPS_COMPOUND_DEVICE !\n");
110             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
111             ret = MCI_RESOURCE_RETURNED;
112             break;
113         case MCI_GETDEVCAPS_CAN_EJECT:
114             TRACE("MCI_GETDEVCAPS_CAN_EJECT !\n");
115             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
116             ret = MCI_RESOURCE_RETURNED;
117             break;
118         case MCI_GETDEVCAPS_CAN_PLAY:
119             TRACE("MCI_GETDEVCAPS_CAN_PLAY !\n");
120             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
121             ret = MCI_RESOURCE_RETURNED;
122             break;
123         case MCI_GETDEVCAPS_CAN_RECORD:
124             TRACE("MCI_GETDEVCAPS_CAN_RECORD !\n");
125             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
126             ret = MCI_RESOURCE_RETURNED;
127             break;
128         case MCI_GETDEVCAPS_CAN_SAVE:
129             TRACE("MCI_GETDEVCAPS_CAN_SAVE !\n");
130             lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
131             ret = MCI_RESOURCE_RETURNED;
132             break;
133         default:
134             FIXME("Unknown capability (%08lx) !\n", lpParms->dwItem);
135            ret = MCIERR_UNRECOGNIZED_COMMAND;
136             break;
137         }
138     } else {
139         WARN("No GetDevCaps-Item !\n");
140        ret = MCIERR_UNRECOGNIZED_COMMAND;
141     }
142
143     LeaveCriticalSection(&wma->cs);
144     return ret;
145 }
146
147 /***************************************************************************
148  *                              MCIAVI_mciInfo                  [internal]
149  */
150 DWORD   MCIAVI_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_INFO_PARMSW lpParms)
151 {
152     LPCWSTR             str = 0;
153     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
154     DWORD               ret = 0;
155     static const WCHAR wszAviPlayer[] = {'W','i','n','e','\'','s',' ','A','V','I',' ','p','l','a','y','e','r',0};
156
157     if (lpParms == NULL || lpParms->lpstrReturn == NULL)
158         return MCIERR_NULL_PARAMETER_BLOCK;
159     if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
160
161     TRACE("buf=%p, len=%lu\n", lpParms->lpstrReturn, lpParms->dwRetSize);
162
163     EnterCriticalSection(&wma->cs);
164
165     if (dwFlags & MCI_INFO_PRODUCT)
166         str = wszAviPlayer;
167     else if (dwFlags & MCI_INFO_FILE)
168         str = wma->lpFileName;
169     else {
170         WARN("Don't know this info command (%lu)\n", dwFlags);
171         ret = MCIERR_UNRECOGNIZED_COMMAND;
172     }
173     if (str) {
174         if (strlenW(str) + 1 > lpParms->dwRetSize) {
175             ret = MCIERR_PARAM_OVERFLOW;
176         } else {
177             lstrcpynW(lpParms->lpstrReturn, str, lpParms->dwRetSize);
178         }
179     } else {
180         lpParms->lpstrReturn[0] = 0;
181     }
182
183     LeaveCriticalSection(&wma->cs);
184     return ret;
185 }
186
187 /***************************************************************************
188  *                              MCIAVI_mciSet                   [internal]
189  */
190 DWORD   MCIAVI_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SET_PARMS lpParms)
191 {
192     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
193
194     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
195     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
196
197     EnterCriticalSection(&wma->cs);
198
199     if (dwFlags & MCI_SET_TIME_FORMAT) {
200         switch (lpParms->dwTimeFormat) {
201         case MCI_FORMAT_MILLISECONDS:
202             TRACE("MCI_FORMAT_MILLISECONDS !\n");
203             wma->dwMciTimeFormat = MCI_FORMAT_MILLISECONDS;
204             break;
205         case MCI_FORMAT_FRAMES:
206             TRACE("MCI_FORMAT_FRAMES !\n");
207             wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
208             break;
209         default:
210             WARN("Bad time format %lu!\n", lpParms->dwTimeFormat);
211             LeaveCriticalSection(&wma->cs);
212             return MCIERR_BAD_TIME_FORMAT;
213         }
214     }
215
216     if (dwFlags & MCI_SET_DOOR_OPEN) {
217         TRACE("No support for door open !\n");
218         LeaveCriticalSection(&wma->cs);
219         return MCIERR_UNSUPPORTED_FUNCTION;
220     }
221     if (dwFlags & MCI_SET_DOOR_CLOSED) {
222         TRACE("No support for door close !\n");
223         LeaveCriticalSection(&wma->cs);
224         return MCIERR_UNSUPPORTED_FUNCTION;
225     }
226
227     if (dwFlags & MCI_SET_ON) {
228         char    buffer[256];
229
230         strcpy(buffer, "MCI_SET_ON:");
231
232         if (dwFlags & MCI_SET_VIDEO) {
233             strncat(buffer, " video", sizeof(buffer));
234             wma->dwSet |= 4;
235         }
236         if (dwFlags & MCI_SET_AUDIO) {
237             strncat(buffer, " audio", sizeof(buffer));
238             switch (lpParms->dwAudio) {
239             case MCI_SET_AUDIO_ALL:
240                 strncat(buffer, " all", sizeof(buffer));
241                 wma->dwSet |= 3;
242                 break;
243             case MCI_SET_AUDIO_LEFT:
244                 strncat(buffer, " left", sizeof(buffer));
245                 wma->dwSet |= 1;
246                 break;
247             case MCI_SET_AUDIO_RIGHT:
248                 strncat(buffer, " right", sizeof(buffer));
249                 wma->dwSet |= 2;
250                 break;
251             default:
252                 WARN("Unknown audio chanel %lu\n", lpParms->dwAudio);
253                 break;
254             }
255         }
256         if (dwFlags & MCI_DGV_SET_SEEK_EXACTLY) {
257             strncat(buffer, " seek_exactly", sizeof(buffer));
258         }
259         FIXME("%s\n", buffer);
260     }
261
262     if (dwFlags & MCI_SET_OFF) {
263         char    buffer[256];
264
265         strcpy(buffer, "MCI_SET_OFF:");
266         if (dwFlags & MCI_SET_VIDEO) {
267             strncat(buffer, " video", sizeof(buffer));
268             wma->dwSet &= ~4;
269         }
270         if (dwFlags & MCI_SET_AUDIO) {
271             strncat(buffer, " audio", sizeof(buffer));
272             switch (lpParms->dwAudio) {
273             case MCI_SET_AUDIO_ALL:
274                 strncat(buffer, " all", sizeof(buffer));
275                 wma->dwSet &= ~3;
276                 break;
277             case MCI_SET_AUDIO_LEFT:
278                 strncat(buffer, " left", sizeof(buffer));
279                 wma->dwSet &= ~2;
280                 break;
281             case MCI_SET_AUDIO_RIGHT:
282                 strncat(buffer, " right", sizeof(buffer));
283                 wma->dwSet &= ~2;
284                 break;
285             default:
286                 WARN("Unknown audio chanel %lu\n", lpParms->dwAudio);
287                 break;
288             }
289         }
290         if (dwFlags & MCI_DGV_SET_SEEK_EXACTLY) {
291             strncat(buffer, " seek_exactly", sizeof(buffer));
292         }
293         FIXME("%s\n", buffer);
294     }
295     if (dwFlags & MCI_DGV_SET_FILEFORMAT) {
296         LPCSTR  str = "save";
297         if (dwFlags & MCI_DGV_SET_STILL)
298             str = "capture";
299
300         switch (lpParms->dwFileFormat) {
301         case MCI_DGV_FF_AVI:    FIXME("Setting file format (%s) to 'AVI'\n", str);      break;
302         case MCI_DGV_FF_AVSS:   FIXME("Setting file format (%s) to 'AVSS'\n", str);     break;
303         case MCI_DGV_FF_DIB:    FIXME("Setting file format (%s) to 'DIB'\n", str);      break;
304         case MCI_DGV_FF_JFIF:   FIXME("Setting file format (%s) to 'JFIF'\n", str);     break;
305         case MCI_DGV_FF_JPEG:   FIXME("Setting file format (%s) to 'JPEG'\n", str);     break;
306         case MCI_DGV_FF_MPEG:   FIXME("Setting file format (%s) to 'MPEG'\n", str);     break;
307         case MCI_DGV_FF_RDIB:   FIXME("Setting file format (%s) to 'RLE DIB'\n", str);  break;
308         case MCI_DGV_FF_RJPEG:  FIXME("Setting file format (%s) to 'RJPEG'\n", str);    break;
309         default:                FIXME("Setting unknown file format (%s): %ld\n", str, lpParms->dwFileFormat);
310         }
311     }
312
313     if (dwFlags & MCI_DGV_SET_SPEED) {
314         FIXME("Setting speed to %ld\n", lpParms->dwSpeed);
315     }
316
317     LeaveCriticalSection(&wma->cs);
318     return 0;
319 }
320
321 /***************************************************************************
322  *                              MCIAVI_mciStatus                        [internal]
323  */
324 DWORD   MCIAVI_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STATUS_PARMSW lpParms)
325 {
326     WINE_MCIAVI*        wma = MCIAVI_mciGetOpenDev(wDevID);
327     DWORD               ret = 0;
328
329     if (lpParms == NULL)        return MCIERR_NULL_PARAMETER_BLOCK;
330     if (wma == NULL)            return MCIERR_INVALID_DEVICE_ID;
331
332     EnterCriticalSection(&wma->cs);
333
334     if (dwFlags & MCI_STATUS_ITEM) {
335         switch (lpParms->dwItem) {
336         case MCI_STATUS_CURRENT_TRACK:
337             lpParms->dwReturn = 1;
338             TRACE("MCI_STATUS_CURRENT_TRACK => %lu\n", lpParms->dwReturn);
339             break;
340         case MCI_STATUS_LENGTH:
341             if (!wma->hFile) {
342                 lpParms->dwReturn = 0;
343                 LeaveCriticalSection(&wma->cs);
344                 return MCIERR_UNSUPPORTED_FUNCTION;
345             }
346             /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
347             lpParms->dwReturn = MCIAVI_ConvertFrameToTimeFormat(wma, wma->mah.dwTotalFrames, &ret);
348             TRACE("MCI_STATUS_LENGTH => %lu\n", lpParms->dwReturn);
349             break;
350         case MCI_STATUS_MODE:
351             lpParms->dwReturn = MAKEMCIRESOURCE(wma->dwStatus, wma->dwStatus);
352             ret = MCI_RESOURCE_RETURNED;
353            TRACE("MCI_STATUS_MODE => 0x%04x\n", LOWORD(lpParms->dwReturn));
354             break;
355         case MCI_STATUS_MEDIA_PRESENT:
356             TRACE("MCI_STATUS_MEDIA_PRESENT => TRUE\n");
357             lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
358             ret = MCI_RESOURCE_RETURNED;
359             break;
360         case MCI_STATUS_NUMBER_OF_TRACKS:
361             lpParms->dwReturn = 1;
362             TRACE("MCI_STATUS_NUMBER_OF_TRACKS => %lu\n", lpParms->dwReturn);
363             break;
364         case MCI_STATUS_POSITION:
365             if (!wma->hFile) {
366                 lpParms->dwReturn = 0;
367                 LeaveCriticalSection(&wma->cs);
368                 return MCIERR_UNSUPPORTED_FUNCTION;
369             }
370             /* only one track in file is currently handled, so don't take care of MCI_TRACK flag */
371             lpParms->dwReturn = MCIAVI_ConvertFrameToTimeFormat(wma,
372                                                              (dwFlags & MCI_STATUS_START) ? 0 : wma->dwCurrVideoFrame,
373                                                              &ret);
374             TRACE("MCI_STATUS_POSITION %s => %lu\n",
375                   (dwFlags & MCI_STATUS_START) ? "start" : "current", lpParms->dwReturn);
376             break;
377         case MCI_STATUS_READY:
378             lpParms->dwReturn = (wma->dwStatus == MCI_MODE_NOT_READY) ?
379                 MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
380             ret = MCI_RESOURCE_RETURNED;
381             TRACE("MCI_STATUS_READY = %u\n", LOWORD(lpParms->dwReturn));
382             break;
383         case MCI_STATUS_TIME_FORMAT:
384             lpParms->dwReturn = MAKEMCIRESOURCE(wma->dwMciTimeFormat,
385                                 wma->dwMciTimeFormat + MCI_FORMAT_RETURN_BASE);
386             TRACE("MCI_STATUS_TIME_FORMAT => %u\n", LOWORD(lpParms->dwReturn));
387             ret = MCI_RESOURCE_RETURNED;
388             break;
389 #if 0
390         case MCI_AVI_STATUS_AUDIO_BREAKS:
391         case MCI_AVI_STATUS_FRAMES_SKIPPED:
392         case MCI_AVI_STATUS_LAST_PLAY_SPEED:
393         case MCI_DGV_STATUS_AUDIO:
394         case MCI_DGV_STATUS_AUDIO_INPUT:
395         case MCI_DGV_STATUS_AUDIO_RECORD:
396         case MCI_DGV_STATUS_AUDIO_SOURCE:
397         case MCI_DGV_SETAUDIO_AVERAGE:
398         case MCI_DGV_SETAUDIO_LEFT:
399         case MCI_DGV_SETAUDIO_RIGHT:
400         case MCI_DGV_SETAUDIO_STEREO:
401         case MCI_DGV_STATUS_AUDIO_STREAM:
402         case MCI_DGV_STATUS_AVGBYTESPERSEC:
403         case MCI_DGV_STATUS_BASS:
404         case MCI_DGV_STATUS_BITSPERPEL:
405         case MCI_DGV_STATUS_BITSPERSAMPLE:
406         case MCI_DGV_STATUS_BLOCKALIGN:
407         case MCI_DGV_STATUS_BRIGHTNESS:
408         case MCI_DGV_STATUS_COLOR:
409         case MCI_DGV_STATUS_CONTRAST:
410         case MCI_DGV_STATUS_FILEFORMAT:
411         case MCI_DGV_STATUS_FILE_MODE:
412         case MCI_DGV_STATUS_FILE_COMPLETION:
413         case MCI_DGV_STATUS_FORWARD:
414         case MCI_DGV_STATUS_FRAME_RATE:
415         case MCI_DGV_STATUS_GAMMA:
416 #endif
417         case MCI_DGV_STATUS_HPAL:
418             lpParms->dwReturn = 0;
419             TRACE("MCI_DGV_STATUS_HPAL => %lx\n", lpParms->dwReturn);
420             break;
421         case MCI_DGV_STATUS_HWND:
422            lpParms->dwReturn = (DWORD_PTR)wma->hWndPaint;
423            TRACE("MCI_DGV_STATUS_HWND => %p\n", wma->hWndPaint);
424             break;
425 #if 0
426         case MCI_DGV_STATUS_KEY_COLOR:
427         case MCI_DGV_STATUS_KEY_INDEX:
428         case MCI_DGV_STATUS_MONITOR:
429         case MCI_DGV_MONITOR_FILE:
430         case MCI_DGV_MONITOR_INPUT:
431         case MCI_DGV_STATUS_MONITOR_METHOD:
432         case MCI_DGV_STATUS_PAUSE_MODE:
433         case MCI_DGV_STATUS_SAMPLESPERSECOND:
434         case MCI_DGV_STATUS_SEEK_EXACTLY:
435         case MCI_DGV_STATUS_SHARPNESS:
436         case MCI_DGV_STATUS_SIZE:
437         case MCI_DGV_STATUS_SMPTE:
438         case MCI_DGV_STATUS_SPEED:
439         case MCI_DGV_STATUS_STILL_FILEFORMAT:
440         case MCI_DGV_STATUS_TINT:
441         case MCI_DGV_STATUS_TREBLE:
442         case MCI_DGV_STATUS_UNSAVED:
443         case MCI_DGV_STATUS_VIDEO:
444         case MCI_DGV_STATUS_VIDEO_RECORD:
445         case MCI_DGV_STATUS_VIDEO_SOURCE:
446         case MCI_DGV_STATUS_VIDEO_SRC_NUM:
447         case MCI_DGV_STATUS_VIDEO_STREAM:
448         case MCI_DGV_STATUS_VOLUME:
449         case MCI_DGV_STATUS_WINDOW_VISIBLE:
450         case MCI_DGV_STATUS_WINDOW_MINIMIZED:
451         case MCI_DGV_STATUS_WINDOW_MAXIMIZED:
452         case MCI_STATUS_MEDIA_PRESENT:
453 #endif
454         default:
455             FIXME("Unknowm command %08lX !\n", lpParms->dwItem);
456             TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);
457             LeaveCriticalSection(&wma->cs);
458             return MCIERR_UNRECOGNIZED_COMMAND;
459         }
460     } else {
461         WARN("No Status-Item!\n");
462         LeaveCriticalSection(&wma->cs);
463         return MCIERR_UNRECOGNIZED_COMMAND;
464     }
465
466     if (dwFlags & MCI_NOTIFY) {
467         TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
468         mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
469                        wDevID, MCI_NOTIFY_SUCCESSFUL);
470     }
471     LeaveCriticalSection(&wma->cs);
472     return ret;
473 }