1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1995 Marcus Meissner
9 * + special commands of device drivers should be handled by those drivers
10 * + this current implementation does not allow commands like
11 * "capability <filename> can play" which is allowed by the MCI standard.
12 * + return value and their conversion to strings (including error codes)
13 * is not coherent with MCI standard.
14 * + digital video interface has not been throughoutfully tested
21 #include <sys/ioctl.h>
23 #include "multimedia.h"
33 DEFAULT_DEBUG_CHANNEL(mci
)
35 /* The reason why I just don't lowercase the keywords array in
36 * mciSendString is left as an exercise to the reader.
37 * (EP: For the blinds, like me, it's linked to file name handling
38 * which is case sensitive).
40 #define STRCMP(x, y) lstrcmpiA(x, y)
42 /* standard function parameters for all functions */
43 #define _MCISTR_PROTO_ \
44 WORD wDevID, WORD uDevTyp, LPSTR lpstrReturnString, \
45 UINT16 uReturnLength, LPCSTR dev, LPSTR* keywords, \
46 UINT16 nrofkeywords, DWORD dwFlags, HWND16 hwndCallback
48 /* copy string to return pointer including necessary checks
49 * for use in mciSendString()
53 TRACE(mci, "-> returns '%s'\n", s); \
54 if (lpstrReturnString) { \
55 lstrcpynA(lpstrReturnString, s, uReturnLength); \
56 TRACE(mci, "--> '%s'\n", lpstrReturnString); \
60 /* print a DWORD in the specified timeformat */
62 _MCISTR_printtf(char *buf
, UINT16 uDevType
, DWORD timef
, DWORD val
)
66 case MCI_FORMAT_MILLISECONDS
:
67 case MCI_FORMAT_FRAMES
:
68 case MCI_FORMAT_BYTES
:
69 case MCI_FORMAT_SAMPLES
:
70 case MCI_VD_FORMAT_TRACK
:
71 /*case MCI_SEQ_FORMAT_SONGPTR: sameas MCI_VD_FORMAT_TRACK */
72 sprintf(buf
, "%ld",val
);
75 /* well, the macros have the same content*/
78 sprintf(buf
, "%d:%d:%d",
84 sprintf(buf
, "%d:%d:%d:%d",
91 FIXME(mci
, "missing timeformat for %ld, report.\n", timef
);
92 strcpy(buf
, "0"); /* hmm */
97 /* possible different return types */
99 #define _MCISTR_time 2
100 #define _MCISTR_bool 3
101 #define _MCISTR_tfname 4
102 #define _MCISTR_mode 5
103 #define _MCISTR_divtype 6
104 #define _MCISTR_seqtype 7
105 #define _MCISTR_vdmtype 8
106 #define _MCISTR_devtype 9
109 _MCISTR_convreturn(int type
, DWORD dwReturn
, LPSTR lpstrReturnString
,
110 WORD uReturnLength
, WORD uDevTyp
, int timef
)
113 case _MCISTR_vdmtype
:
115 case MCI_VD_MEDIA_CLV
: _MCI_STR("CLV"); break;
116 case MCI_VD_MEDIA_CAV
: _MCI_STR("CAV"); break;
118 case MCI_VD_MEDIA_OTHER
:_MCI_STR("other"); break;
121 case _MCISTR_seqtype
:
123 case MCI_SEQ_NONE
: _MCI_STR("none"); break;
124 case MCI_SEQ_SMPTE
: _MCI_STR("smpte"); break;
125 case MCI_SEQ_FILE
: _MCI_STR("file"); break;
126 case MCI_SEQ_MIDI
: _MCI_STR("midi"); break;
127 default:FIXME(mci
, "missing sequencer mode %ld\n", dwReturn
);
132 case MCI_MODE_NOT_READY
:_MCI_STR("not ready"); break;
133 case MCI_MODE_STOP
: _MCI_STR("stopped"); break;
134 case MCI_MODE_PLAY
: _MCI_STR("playing"); break;
135 case MCI_MODE_RECORD
: _MCI_STR("recording"); break;
136 case MCI_MODE_SEEK
: _MCI_STR("seeking"); break;
137 case MCI_MODE_PAUSE
: _MCI_STR("paused"); break;
138 case MCI_MODE_OPEN
: _MCI_STR("open"); break;
150 sprintf(buf
, "%ld", dwReturn
);
156 _MCISTR_printtf(buf
, uDevTyp
, timef
, dwReturn
);
162 case MCI_FORMAT_MILLISECONDS
: _MCI_STR("milliseconds"); break;
163 case MCI_FORMAT_FRAMES
: _MCI_STR("frames"); break;
164 case MCI_FORMAT_BYTES
: _MCI_STR("bytes"); break;
165 case MCI_FORMAT_SAMPLES
: _MCI_STR("samples"); break;
166 case MCI_FORMAT_HMS
: _MCI_STR("hms"); break;
167 case MCI_FORMAT_MSF
: _MCI_STR("msf"); break;
168 case MCI_FORMAT_TMSF
: _MCI_STR("tmsf"); break;
170 FIXME(mci
, "missing timefmt for %d, report.\n", timef
);
174 case _MCISTR_divtype
:
176 case MCI_SEQ_DIV_PPQN
: _MCI_STR("PPQN"); break;
177 case MCI_SEQ_DIV_SMPTE_24
: _MCI_STR("SMPTE 24 frame"); break;
178 case MCI_SEQ_DIV_SMPTE_25
: _MCI_STR("SMPTE 25 frame"); break;
179 case MCI_SEQ_DIV_SMPTE_30
: _MCI_STR("SMPTE 30 frame"); break;
180 case MCI_SEQ_DIV_SMPTE_30DROP
: _MCI_STR("SMPTE 30 frame drop");break;
182 case _MCISTR_devtype
:
184 case MCI_DEVTYPE_VCR
: _MCI_STR("vcr"); break;
185 case MCI_DEVTYPE_VIDEODISC
: _MCI_STR("videodisc"); break;
186 case MCI_DEVTYPE_CD_AUDIO
: _MCI_STR("cd audio"); break;
187 case MCI_DEVTYPE_OVERLAY
: _MCI_STR("overlay"); break;
188 case MCI_DEVTYPE_DAT
: _MCI_STR("dat"); break;
189 case MCI_DEVTYPE_SCANNER
: _MCI_STR("scanner"); break;
190 case MCI_DEVTYPE_ANIMATION
: _MCI_STR("animation"); break;
191 case MCI_DEVTYPE_DIGITAL_VIDEO
: _MCI_STR("digital video"); break;
192 case MCI_DEVTYPE_OTHER
: _MCI_STR("other"); break;
193 case MCI_DEVTYPE_WAVEFORM_AUDIO
:_MCI_STR("waveform audio"); break;
194 case MCI_DEVTYPE_SEQUENCER
: _MCI_STR("sequencer"); break;
195 default:FIXME(mci
, "unknown device type %ld, report.\n",
200 FIXME(mci
, "unknown resulttype %d, report.\n", type
);
205 #define FLAG1(str, flag) \
206 if (!STRCMP(keywords[i], str)) { \
212 #define FLAG2(str1, str2, flag) \
213 if (!STRCMP(keywords[i], str1) && \
214 (i+1 < nrofkeywords) && \
215 !STRCMP(keywords[i+1], str2)) { \
221 /* All known subcommands are implemented in single functions to avoid
222 * bloat and a xxxx lines long mciSendString(). All commands are of the
223 * format MCISTR_Cmd(_MCISTR_PROTO_) where _MCISTR_PROTO_ is the above
224 * defined line of arguments. (This is just for easy enhanceability.)
225 * All functions return the MCIERR_ errorvalue as DWORD. Returnvalues
226 * for the calls are in lpstrReturnString (If I mention return values
227 * in function headers, I mean returnvalues in lpstrReturnString.)
228 * Integers are sprintf("%d")ed integers. Boolean values are
229 * "true" and "false".
230 * timeformat depending values are "%d" "%d:%d" "%d:%d:%d" "%d:%d:%d:%d"
231 * FIXME: is above line correct?
233 * Preceding every function is a list of implemented/known arguments.
234 * Feel free to add missing arguments.
239 * Opens the specified MCI driver.
243 * "alias <aliasname>"
244 * "element <elementname>"
247 * "buffer <nrBytesPerSec>"
249 * "nostatic" increaste nr of nonstatic colours
250 * "parent <windowhandle>"
251 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
252 * "style child" WS_CHILD
253 * "style overlap" WS_OVERLAPPED
254 * "style popup" WS_POPUP
256 * "parent <windowhandle>"
257 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
258 * "style child" WS_CHILD
259 * "style overlap" WS_OVERLAPPED
260 * "style popup" WS_POPUP
264 MCISTR_Open(_MCISTR_PROTO_
)
269 MCI_OPEN_PARMSA openParams
;
270 MCI_WAVE_OPEN_PARMSA waveopenParams
;
271 MCI_ANIM_OPEN_PARMSA animopenParams
;
272 MCI_OVLY_OPEN_PARMSA ovlyopenParams
;
273 MCI_DGV_OPEN_PARMSA dgvopenParams
;
275 union U
* pU
= xmalloc(sizeof(union U
));
277 pU
->openParams
.lpstrElementName
= NULL
;
278 s
= strchr(dev
, '!');
281 pU
->openParams
.lpstrElementName
= strdup(s
);
282 dwFlags
|= MCI_OPEN_ELEMENT
;
284 for (i
= 0; i
< nrofkeywords
; ) {
285 if ((!STRCMP(keywords
[i
], "type")) && (i
< nrofkeywords
-1)) {
286 pU
->openParams
.lpstrElementName
= strdup(dev
);
287 dwFlags
|= MCI_OPEN_ELEMENT
;
289 /* FIXME: isn't there a memory leak here ? keyword+i ? */
290 memcpy(keywords
+i
, keywords
+(i
+2), (nrofkeywords
-i
-2) * sizeof(char*));
297 CharUpperA((char*)dev
);
298 uDevTyp
= MCI_GetDevTypeFromString(dev
);
300 free(pU
->openParams
.lpstrElementName
);
302 return MCIERR_INVALID_DEVICE_NAME
;
305 pU
->openParams
.dwCallback
= hwndCallback
;
306 pU
->openParams
.wDeviceID
= wDevID
;
307 pU
->ovlyopenParams
.dwStyle
= 0;
308 pU
->animopenParams
.dwStyle
= 0;
309 pU
->openParams
.lpstrDeviceType
= strdup(dev
);
310 pU
->openParams
.lpstrAlias
= NULL
;
311 dwFlags
|= MCI_OPEN_TYPE
;
312 for (i
= 0; i
< nrofkeywords
; ) {
313 FLAG1("shareable", MCI_OPEN_SHAREABLE
);
314 if (!STRCMP(keywords
[i
], "alias") && (i
+1 < nrofkeywords
)) {
315 dwFlags
|= MCI_OPEN_ALIAS
;
316 pU
->openParams
.lpstrAlias
= strdup(keywords
[i
+1]);
320 if (!STRCMP(keywords
[i
], "element") && (i
+1 < nrofkeywords
)) {
321 dwFlags
|= MCI_OPEN_ELEMENT
;
322 assert(pU
->openParams
.lpstrElementName
== NULL
);
323 pU
->openParams
.lpstrElementName
= strdup(keywords
[i
+1]);
328 case MCI_DEVTYPE_ANIMATION
:
329 FLAG1("nostatic", MCI_ANIM_OPEN_NOSTATIC
);
330 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
331 dwFlags
|= MCI_ANIM_OPEN_PARENT
;
332 sscanf(keywords
[i
+1], "%u", &(pU
->animopenParams
.hWndParent
));
336 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
339 dwFlags
|= MCI_ANIM_OPEN_WS
;
340 if (!STRCMP(keywords
[i
+1], "popup")) {
341 pU
->animopenParams
.dwStyle
|= WS_POPUP
;
342 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
343 pU
->animopenParams
.dwStyle
|= WS_OVERLAPPED
;
344 } else if (!STRCMP(keywords
[i
+1], "child")) {
345 pU
->animopenParams
.dwStyle
|= WS_CHILD
;
346 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
347 pU
->animopenParams
.dwStyle
|= st
;
349 FIXME(mci
, "unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
354 case MCI_DEVTYPE_DIGITAL_VIDEO
:
355 FLAG1("nostatic", MCI_ANIM_OPEN_NOSTATIC
);
356 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
357 dwFlags
|= MCI_DGV_OPEN_PARENT
;
358 sscanf(keywords
[i
+1], "%u", &(pU
->dgvopenParams
.hWndParent
));
362 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
365 dwFlags
|= MCI_DGV_OPEN_WS
;
366 if (!STRCMP(keywords
[i
+1], "popup")) {
367 pU
->dgvopenParams
.dwStyle
|= WS_POPUP
;
368 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
369 pU
->dgvopenParams
.dwStyle
|= WS_OVERLAPPED
;
370 } else if (!STRCMP(keywords
[i
+1], "child")) {
371 pU
->dgvopenParams
.dwStyle
|= WS_CHILD
;
372 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
373 pU
->dgvopenParams
.dwStyle
|= st
;
375 FIXME(mci
, "unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
380 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
381 if (!STRCMP(keywords
[i
], "buffer") && (i
+1 < nrofkeywords
)) {
382 dwFlags
|= MCI_WAVE_OPEN_BUFFER
;
383 sscanf(keywords
[i
+1], "%ld", &(pU
->waveopenParams
.dwBufferSeconds
));
386 case MCI_DEVTYPE_OVERLAY
:
387 /* looks just like anim, but without NOSTATIC */
388 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
389 dwFlags
|= MCI_OVLY_OPEN_PARENT
;
390 sscanf(keywords
[i
+1], "%u", &(pU
->ovlyopenParams
.hWndParent
));
394 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
397 dwFlags
|= MCI_OVLY_OPEN_WS
;
398 if (!STRCMP(keywords
[i
+1], "popup")) {
399 pU
->ovlyopenParams
.dwStyle
|= WS_POPUP
;
400 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
401 pU
->ovlyopenParams
.dwStyle
|= WS_OVERLAPPED
;
402 } else if (!STRCMP(keywords
[i
+1], "child")) {
403 pU
->ovlyopenParams
.dwStyle
|= WS_CHILD
;
404 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
405 pU
->ovlyopenParams
.dwStyle
|= st
;
407 FIXME(mci
, "unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
413 FIXME(mci
, "unknown parameter passed %s, please report.\n",
417 res
= mciSendCommandA(0, MCI_OPEN
, dwFlags
, (DWORD
)pU
);
419 free(pU
->openParams
.lpstrElementName
);
420 free(pU
->openParams
.lpstrDeviceType
);
421 free(pU
->openParams
.lpstrAlias
);
426 /* A helper function for a lot of others ...
427 * for instance status/play/record/seek etc.
430 _MCISTR_determine_timeformat(LPCSTR dev
, WORD wDevID
, WORD uDevTyp
, int *timef
)
433 DWORD dwFlags
= MCI_STATUS_ITEM
;
434 LPMCI_STATUS_PARMS statusParams
= xmalloc(sizeof(MCI_STATUS_PARMS
));
436 if (!statusParams
) return 0;
437 statusParams
->dwItem
= MCI_STATUS_TIME_FORMAT
;
438 statusParams
->dwReturn
= 0;
439 res
= mciSendCommandA(wDevID
, MCI_STATUS
, dwFlags
, (DWORD
)statusParams
);
441 if (res
== 0) *timef
= statusParams
->dwReturn
;
446 /* query status of MCI drivers
449 * "mode" - returns "not ready" "paused" "playing" "stopped" "open"
450 * "parked" "recording" "seeking" ....
452 * "current track" - returns current track as integer
453 * "length [track <nr>]" - returns length [of track <nr>] in current
455 * "number of tracks" - returns number of tracks as integer
456 * "position [track <nr>]" - returns position [in track <nr>] in current
458 * "ready" - checks if device is ready to play, -> bool
459 * "start position" - returns start position in timeformat
460 * "time format" - returns timeformat (list of possible values:
461 * "ms" "msf" "milliseconds" "hmsf" "tmsf" "frames"
462 * "bytes" "samples" "hms")
463 * "media present" - returns if media is present as bool
465 * "forward" - returns "true" if device is playing forwards
466 * "speed" - returns speed for device
467 * "palette handle" - returns palette handle
468 * "window handle" - returns window handle
469 * "stretch" - returns stretch bool
471 * "division type" - ? returns "PPQN" "SMPTE 24 frame"
472 * "SMPTE 25 frame" "SMPTE 30 frame" "SMPTE 30 drop frame"
473 * "tempo" - current tempo in (PPQN? speed in frames, SMPTE*? speed in hsmf)
474 * "offset" - offset in dito.
475 * "port" - midi port as integer
476 * "slave" - slave device ("midi", "file", "none", "smpte")
477 * "master" - masterdevice (dito.)
479 * "window handle" - see animation
482 * "speed" - speed as integer
483 * "forward" - returns bool (when playing forward)
484 * "side" - returns 1 or 2
485 * "media type" - returns "CAV" "CLV" "other"
486 * "disc size" - returns "8" or "12"
488 * "input" - base queries on input set
489 * "output" - base queries on output set
490 * "format tag" - return integer format tag
491 * "channels" - return integer nr of channels
492 * "bytespersec" - return average nr of bytes/sec
493 * "samplespersec" - return nr of samples per sec
494 * "bitspersample" - return bitspersample
495 * "alignment" - return block alignment
496 * "level" - return level?
500 * "audio bitspersample"
502 * "audio bytespersec"
506 * "audio samplespersec"
527 * "nominal frame rate"
528 * "nominal record frame rate"
533 * "record frame rate"
541 * "still file format"
550 * "video source number"
559 #define ITEM1(str, item, xtype) \
560 if (!STRCMP(keywords[i], str)) { \
561 pU->statusParams.dwItem = item; \
566 #define ITEM2(str1, str2, item, xtype) \
567 if ( !STRCMP(keywords[i], str1) && \
568 (i+1 < nrofkeywords) && \
569 !STRCMP(keywords[i+1], str2)) { \
570 pU->statusParams.dwItem = item; \
575 #define ITEM3(str1, str2, str3, item, xtype) \
576 if ( !STRCMP(keywords[i], str1) && \
577 (i+2 < nrofkeywords) && \
578 !STRCMP(keywords[i+1], str2) && \
579 !STRCMP(keywords[i+2], str3)) { \
580 pU->statusParams.dwItem = item; \
585 #define ITEM4(str1, str2, str3, str4, item, xtype) \
586 if ( !STRCMP(keywords[i], str1) && \
587 (i+3 < nrofkeywords) && \
588 !STRCMP(keywords[i+1], str2) && \
589 !STRCMP(keywords[i+2], str3) && \
590 !STRCMP(keywords[i+3], str4)) { \
591 pU->statusParams.dwItem = item; \
598 MCISTR_Status(_MCISTR_PROTO_
) {
600 MCI_STATUS_PARMS statusParams
;
601 MCI_DGV_STATUS_PARMSA dgvstatusParams
;
603 union U
* pU
= xmalloc(sizeof(union U
));
604 int type
= 0, i
, res
, timef
;
606 pU
->statusParams
.dwCallback
= hwndCallback
;
607 dwFlags
|= MCI_STATUS_ITEM
;
608 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
611 pU
->statusParams
.dwReturn
= 0;
612 pU
->statusParams
.dwItem
= 0;
614 for (i
= 0; i
< nrofkeywords
; ) {
615 if (!STRCMP(keywords
[i
], "track") && (i
+1 < nrofkeywords
)) {
616 sscanf(keywords
[i
+1], "%ld", &(pU
->statusParams
.dwTrack
));
617 dwFlags
|= MCI_TRACK
;
621 FLAG1("start", MCI_STATUS_START
);
623 ITEM2("current", "track", MCI_STATUS_CURRENT_TRACK
, _MCISTR_time
);
624 ITEM2("time", "format", MCI_STATUS_TIME_FORMAT
, _MCISTR_tfname
);
625 ITEM1("ready", MCI_STATUS_READY
, _MCISTR_bool
);
626 ITEM1("mode", MCI_STATUS_MODE
, _MCISTR_mode
);
627 ITEM3("number", "of", "tracks", MCI_STATUS_NUMBER_OF_TRACKS
, _MCISTR_int
);
628 ITEM1("length", MCI_STATUS_LENGTH
, _MCISTR_time
);
629 ITEM1("position", MCI_STATUS_POSITION
, _MCISTR_time
);
630 ITEM2("media", "present", MCI_STATUS_MEDIA_PRESENT
, _MCISTR_bool
);
633 case MCI_DEVTYPE_ANIMATION
:
634 ITEM2("palette", "handle", MCI_ANIM_STATUS_HPAL
, _MCISTR_int
);
635 ITEM2("window", "handle", MCI_ANIM_STATUS_HWND
, _MCISTR_int
);
636 ITEM1("stretch", MCI_ANIM_STATUS_STRETCH
, _MCISTR_bool
);
637 ITEM1("speed", MCI_ANIM_STATUS_SPEED
, _MCISTR_int
);
638 ITEM1("forward", MCI_ANIM_STATUS_FORWARD
, _MCISTR_bool
);
640 case MCI_DEVTYPE_SEQUENCER
:
641 /* just completing the list, not working correctly */
642 ITEM2("division", "type", MCI_SEQ_STATUS_DIVTYPE
, _MCISTR_divtype
);
643 /* tempo ... PPQN in frames/second, SMPTE in hmsf */
644 ITEM1("tempo", MCI_SEQ_STATUS_TEMPO
, _MCISTR_int
);
645 ITEM1("port", MCI_SEQ_STATUS_PORT
, _MCISTR_int
);
646 ITEM1("slave", MCI_SEQ_STATUS_SLAVE
, _MCISTR_seqtype
);
647 ITEM1("master", MCI_SEQ_STATUS_SLAVE
, _MCISTR_seqtype
);
648 /* offset ... PPQN in frames/second, SMPTE in hmsf */
649 ITEM1("offset", MCI_SEQ_STATUS_SLAVE
, _MCISTR_time
);
651 case MCI_DEVTYPE_OVERLAY
:
652 ITEM2("window", "handle", MCI_OVLY_STATUS_HWND
, _MCISTR_int
);
653 ITEM1("stretch", MCI_OVLY_STATUS_STRETCH
, _MCISTR_bool
);
655 case MCI_DEVTYPE_VIDEODISC
:
656 ITEM1("speed", MCI_VD_STATUS_SPEED
, _MCISTR_int
);
657 ITEM1("forward", MCI_VD_STATUS_FORWARD
, _MCISTR_bool
);
658 ITEM1("side", MCI_VD_STATUS_SIDE
, _MCISTR_int
);
659 ITEM2("media", "type", MCI_VD_STATUS_SIDE
, _MCISTR_vdmtype
);
660 /* returns 8 or 12 */
661 ITEM2("disc", "size", MCI_VD_STATUS_DISC_SIZE
, _MCISTR_int
);
663 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
664 /* I am not quite sure if foll. 2 lines are right. */
665 FLAG1("input", MCI_WAVE_INPUT
);
666 FLAG1("output", MCI_WAVE_OUTPUT
);
668 ITEM2("format", "tag", MCI_WAVE_STATUS_FORMATTAG
, _MCISTR_int
);
669 ITEM1("channels", MCI_WAVE_STATUS_CHANNELS
, _MCISTR_int
);
670 ITEM1("bytespersec", MCI_WAVE_STATUS_AVGBYTESPERSEC
, _MCISTR_int
);
671 ITEM1("samplespersec", MCI_WAVE_STATUS_SAMPLESPERSEC
, _MCISTR_int
);
672 ITEM1("bitspersample", MCI_WAVE_STATUS_BITSPERSAMPLE
, _MCISTR_int
);
673 ITEM1("alignment", MCI_WAVE_STATUS_BLOCKALIGN
, _MCISTR_int
);
674 ITEM1("level", MCI_WAVE_STATUS_LEVEL
, _MCISTR_int
);
676 case MCI_DEVTYPE_DIGITAL_VIDEO
:
677 ITEM1("audio", MCI_DGV_STATUS_AUDIO
, _MCISTR_bool
); /* FIXME? doc says MCI_ON/MCI_OFF */
678 ITEM2("audio", "alignment", MCI_DGV_STATUS_BLOCKALIGN
, _MCISTR_int
);
679 ITEM2("audio", "bitspersample", MCI_DGV_STATUS_BITSPERSAMPLE
, _MCISTR_int
);
680 /* EPP ITEM2("audio", "breaks", MCI_AVI_STATUS_AUDIO_BREAKS, _MCISTR_int); */
681 ITEM2("audio", "bytespersec", MCI_DGV_STATUS_AVGBYTESPERSEC
, _MCISTR_int
);
682 ITEM2("audio", "input", MCI_DGV_STATUS_AUDIO_INPUT
, _MCISTR_int
);
683 ITEM2("audio", "record", MCI_DGV_STATUS_AUDIO_RECORD
, _MCISTR_bool
); /* FIXME? doc says MCI_ON/MCI_OFF */
684 ITEM3("audio", "source", "number", MCI_DGV_STATUS_AUDIO_SOURCE
, _MCISTR_int
);
685 /* FIXME: ITEM2("audio", "source", MCI_DGV_STATUS_AUDIO_SOURCE, _MCISTR_dgvaudiosource); */
686 /* EPP ITEM2("audio", "samplespersec", MCI_DGV_STATUS_SAMPLESPERSECOND, _MCISTR_int); */
687 ITEM2("audio", "stream", MCI_DGV_STATUS_AUDIO_STREAM
, _MCISTR_int
);
688 ITEM1("bass", MCI_DGV_STATUS_BASS
, _MCISTR_int
);
689 ITEM1("bitsperpel", MCI_DGV_STATUS_BITSPERPEL
, _MCISTR_int
);
690 ITEM1("brightness", MCI_DGV_STATUS_BRIGHTNESS
, _MCISTR_int
);
691 ITEM1("color", MCI_DGV_STATUS_COLOR
, _MCISTR_int
);
692 ITEM1("contrast", MCI_DGV_STATUS_CONTRAST
, _MCISTR_int
);
693 /* EPP * "disk space drive" FIXME */
694 ITEM2("file", "completion", MCI_DGV_STATUS_FILE_COMPLETION
, _MCISTR_int
);
695 /* EPP ITEM2("file", "format", MCI_DGV_STATUS_FILEFORMAT, _MCISTR_???); */
696 /* EPP ITEM2("file", "mode", MCI_DGV_STATUS_FILE_MODE, _MCISTR_gdvfileformat); */
697 ITEM1("forward", MCI_DGV_STATUS_FORWARD
, _MCISTR_bool
);
698 /* EPP ITEM2("frames", "skipped", MCI_AVI_STATUS_FRAMES_SKIPPED, _MCISTR_int); */
699 ITEM1("gamma", MCI_DGV_STATUS_GAMMA
, _MCISTR_int
);
700 ITEM2("input", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
701 ITEM2("input", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
702 ITEM2("input", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
703 ITEM2("input", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
704 ITEM2("input", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
705 ITEM2("input", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
706 ITEM2("input", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
707 ITEM2("input", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
709 ITEM2("left", "volume", MCI_DGV_STATUS_VOLUME
|MCI_DGV_STATUS_LEFT
, _MCISTR_int
);
710 ITEM2("media", "present", MCI_STATUS_MEDIA_PRESENT
, _MCISTR_bool
);
711 /* EPP ITEM2("monitor", "method", MCI_DGV_STATUS_MONITOR_METHOD, _MCISTR_monitor); */
712 /* EPP ITEM1("monitor", MCI_DGV_STATUS_MONITOR, _MCISTR_monitor2); */
713 ITEM2("nominal", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
714 ITEM2("nominal", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
715 ITEM2("nominal", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
716 ITEM2("nominal", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
717 ITEM2("nominal", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
718 ITEM2("nominal", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
719 ITEM2("nominal", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
720 ITEM2("nominal", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
721 ITEM3("nominal", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
722 ITEM4("nominal", "record", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_RECORD
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
723 ITEM2("output", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
724 ITEM2("output", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
725 ITEM2("output", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
726 ITEM2("output", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
727 ITEM2("output", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
728 ITEM2("output", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
729 ITEM2("output", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
730 ITEM2("output", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
731 ITEM2("palette", "handle", MCI_DGV_STATUS_HPAL
, _MCISTR_int
); /* FIXME? */
732 ITEM2("pause", "mode", MCI_DGV_STATUS_PAUSE_MODE
, _MCISTR_bool
); /* FIXME */
733 /* EPP ITEM2("play", "speed", MCI_AVI_STATUS_LAST_PLAY_SPEED, _MCISTR_int); */
734 ITEM3("record", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_RECORD
, _MCISTR_int
);
735 ITEM2("reference", "frame", MCI_DGV_STATUS_FRAME_RATE
, _MCISTR_int
); /* FIXME */
736 ITEM2("reserved", "size", MCI_DGV_STATUS_SIZE
, _MCISTR_int
);
737 ITEM2("right", "volume", MCI_DGV_STATUS_VOLUME
|MCI_DGV_STATUS_RIGHT
, _MCISTR_int
);
738 ITEM2("seek", "exactly", MCI_DGV_STATUS_SEEK_EXACTLY
, _MCISTR_bool
);
739 ITEM1("sharpness", MCI_DGV_STATUS_SHARPNESS
, _MCISTR_int
);
740 /* EPP ITEM1("smpte", MCI_DGV_STATUS_SMPTE, _MCISTR_smpte); */
741 /* EPP ITEM1("speed", MCI_DGV_STATUS_SPEED, _MCISTR_speed); */
742 /* EPP ITEM3("still", "file", "format", MCI_DGV_STATUS_STILL_FILEFORMAT, _MCISTR_???); */
743 ITEM1("tint", MCI_DGV_STATUS_TINT
, _MCISTR_int
);
744 ITEM1("treble", MCI_DGV_STATUS_TREBLE
, _MCISTR_int
);
745 ITEM1("unsaved", MCI_DGV_STATUS_UNSAVED
, _MCISTR_bool
);
746 ITEM3("video", "key", "index", MCI_DGV_STATUS_KEY_INDEX
, _MCISTR_int
);
747 ITEM3("video", "key", "color", MCI_DGV_STATUS_KEY_COLOR
, _MCISTR_bool
);
748 ITEM2("video", "record", MCI_DGV_STATUS_VIDEO_RECORD
, _MCISTR_bool
); /* FIXME MCI_ON/OFF */
749 ITEM3("video", "source", "number", MCI_DGV_STATUS_VIDEO_SOURCE
, _MCISTR_int
);
750 /* EPP ITEM2("video", "source", MCI_DGV_STATUS_VIDEO_SOURCE, _MCISTR_videosrctype); */
751 ITEM2("video", "stream", MCI_DGV_STATUS_VIDEO_STREAM
, _MCISTR_int
);
752 ITEM1("video", MCI_DGV_STATUS_VIDEO
, _MCISTR_bool
); /* FIXME MCI_ON/OFF */
753 ITEM1("volume", MCI_DGV_STATUS_VOLUME
, _MCISTR_int
);
754 ITEM2("window", "handle", MCI_DGV_STATUS_HWND
, _MCISTR_int
);
755 ITEM2("window", "visible", MCI_DGV_STATUS_WINDOW_VISIBLE
, _MCISTR_bool
);
756 ITEM2("window", "minimized", MCI_DGV_STATUS_WINDOW_MINIMIZED
, _MCISTR_bool
);
757 ITEM2("window", "maximized",MCI_DGV_STATUS_WINDOW_MAXIMIZED
, _MCISTR_bool
);
760 FIXME(mci
, "unknown keyword '%s'\n", keywords
[i
]);
763 if (!pU
->statusParams
.dwItem
)
764 return MCIERR_MISSING_STRING_ARGUMENT
;
766 res
= mciSendCommandA(wDevID
, MCI_STATUS
, dwFlags
, (DWORD
)pU
);
769 _MCISTR_convreturn(type
, pU
->statusParams
.dwReturn
, lpstrReturnString
, uReturnLength
, uDevTyp
, timef
);
778 /* set specified parameters in respective MCI drivers
780 * "door open" eject media or somesuch
781 * "door close" load media
782 * "time format <timeformatname>" "ms" "milliseconds" "msf" "hmsf"
783 * "tmsf" "SMPTE 24" "SMPTE 25" "SMPTE 30"
785 * "audio [all|left|right] [on|off]" sets specified audiochannel on or off
786 * "video [on|off]" sets video on/off
788 * "formattag pcm" sets format to pcm
789 * "formattag <nr>" sets integer formattag value
790 * "any input" accept input from any known source
791 * "any output" output to any known destination
792 * "input <nr>" input from source <nr>
793 * "output <nr>" output to destination <nr>
794 * "channels <nr>" sets nr of channels
795 * "bytespersec <nr>" sets average bytes per second
796 * "samplespersec <nr>" sets average samples per second (1 sample can
798 * "alignment <nr>" sets the blockalignment to <nr>
799 * "bitspersample <nr>" sets the nr of bits per sample
801 * "master [midi|file|smpte|none]" sets the midi master device
802 * "slave [midi|file|smpte|none]" sets the midi master device
803 * "port mapper" midioutput to portmapper
804 * "port <nr>" midioutput to specified port
805 * "tempo <nr>" tempo of track (depends on timeformat/divtype)
806 * "offset <nr>" start offset?
809 MCISTR_Set(_MCISTR_PROTO_
) {
811 MCI_SET_PARMS setParams
;
812 MCI_WAVE_SET_PARMS wavesetParams
;
813 MCI_SEQ_SET_PARMS seqsetParams
;
815 union U
* pU
= xmalloc(sizeof(union U
));
818 pU
->setParams
.dwCallback
= hwndCallback
;
820 for (i
= 0; i
< nrofkeywords
; ) {
821 FLAG2("door", "open", MCI_SET_DOOR_OPEN
);
822 FLAG2("door", "closed", MCI_SET_DOOR_CLOSED
);
824 if (!STRCMP(keywords
[i
], "time") && (i
+2 < nrofkeywords
) && !STRCMP(keywords
[i
+1], "format")) {
825 dwFlags
|= MCI_SET_TIME_FORMAT
;
827 /* FIXME:is this a shortcut for milliseconds or
828 * minutes:seconds? */
829 if (!STRCMP(keywords
[i
+2], "ms"))
830 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
832 if (!STRCMP(keywords
[i
+2], "milliseconds"))
833 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
834 if (!STRCMP(keywords
[i
+2], "msf"))
835 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MSF
;
836 if (!STRCMP(keywords
[i
+2], "hms"))
837 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_HMS
;
838 if (!STRCMP(keywords
[i
+2], "frames"))
839 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_FRAMES
;
840 if (!STRCMP(keywords
[i
+2], "track"))
841 pU
->setParams
.dwTimeFormat
= MCI_VD_FORMAT_TRACK
;
842 if (!STRCMP(keywords
[i
+2], "bytes"))
843 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_BYTES
;
844 if (!STRCMP(keywords
[i
+2], "samples"))
845 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SAMPLES
;
846 if (!STRCMP(keywords
[i
+2], "tmsf"))
847 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_TMSF
;
848 if ( !STRCMP(keywords
[i
+2], "song") &&
849 (i
+3 < nrofkeywords
) &&
850 !STRCMP(keywords
[i
+3], "pointer")
852 pU
->setParams
.dwTimeFormat
= MCI_SEQ_FORMAT_SONGPTR
;
853 if (!STRCMP(keywords
[i
+2], "smpte") && (i
+3 < nrofkeywords
)) {
854 if (!STRCMP(keywords
[i
+3], "24"))
855 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_24
;
856 if (!STRCMP(keywords
[i
+3], "25"))
857 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_25
;
858 if (!STRCMP(keywords
[i
+3], "30"))
859 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30
;
860 if (!STRCMP(keywords
[i
+3], "drop") && (i
+4 < nrofkeywords
) && !STRCMP(keywords
[i
+4], "30")) {
861 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30DROP
;
870 if (!STRCMP(keywords
[i
], "audio") && (i
+1 < nrofkeywords
)) {
871 dwFlags
|= MCI_SET_AUDIO
;
872 if (!STRCMP(keywords
[i
+1], "all"))
873 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_ALL
;
874 if (!STRCMP(keywords
[i
+1], "left"))
875 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_LEFT
;
876 if (!STRCMP(keywords
[i
+1], "right"))
877 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_RIGHT
;
881 FLAG1("video", MCI_SET_VIDEO
);
882 FLAG1("on", MCI_SET_ON
);
883 FLAG1("off", MCI_SET_OFF
);
885 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
886 FLAG2("any", "input", MCI_WAVE_SET_ANYINPUT
);
887 FLAG2("any", "output", MCI_WAVE_SET_ANYOUTPUT
);
889 if ( !STRCMP(keywords
[i
], "formattag") &&
890 (i
+1 < nrofkeywords
) &&
891 !STRCMP(keywords
[i
+1], "pcm")
893 dwFlags
|= MCI_WAVE_SET_FORMATTAG
;
894 pU
->wavesetParams
.wFormatTag
= WAVE_FORMAT_PCM
;
899 /* <keyword> <integer> */
900 #define WII(str,flag,fmt,element) \
901 if (!STRCMP(keywords[i], str) && \
902 (i+1 < nrofkeywords)) { \
903 sscanf(keywords[i+1], fmt, \
904 &(pU->wavesetParams. element)); \
909 WII("formattag", MCI_WAVE_SET_FORMATTAG
, "%u", wFormatTag
);
910 WII("channels", MCI_WAVE_SET_CHANNELS
, "%u", nChannels
);
911 WII("bytespersec", MCI_WAVE_SET_AVGBYTESPERSEC
, "%lu", nAvgBytesPerSec
);
912 WII("samplespersec", MCI_WAVE_SET_SAMPLESPERSEC
, "%lu", nSamplesPerSec
);
913 WII("alignment", MCI_WAVE_SET_BLOCKALIGN
, "%u", nBlockAlign
);
914 WII("bitspersample", MCI_WAVE_SET_BITSPERSAMPLE
, "%u", wBitsPerSample
);
915 WII("input", MCI_WAVE_INPUT
, "%u", wInput
);
916 WII("output", MCI_WAVE_OUTPUT
, "%u", wOutput
);
919 case MCI_DEVTYPE_SEQUENCER
:
920 if (!STRCMP(keywords
[i
], "master") && (i
+1 < nrofkeywords
)) {
921 dwFlags
|= MCI_SEQ_SET_MASTER
;
922 if (!STRCMP(keywords
[i
+1], "midi"))
923 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
924 if (!STRCMP(keywords
[i
+1], "file"))
925 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
926 if (!STRCMP(keywords
[i
+1], "smpte"))
927 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
928 if (!STRCMP(keywords
[i
+1], "none"))
929 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
933 if (!STRCMP(keywords
[i
], "slave") && (i
+1 < nrofkeywords
)) {
934 dwFlags
|= MCI_SEQ_SET_SLAVE
;
935 if (!STRCMP(keywords
[i
+1], "midi"))
936 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
937 if (!STRCMP(keywords
[i
+1], "file"))
938 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
939 if (!STRCMP(keywords
[i
+1], "smpte"))
940 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
941 if (!STRCMP(keywords
[i
+1], "none"))
942 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
946 if ( !STRCMP(keywords
[i
], "port") &&
947 (i
+1 < nrofkeywords
) &&
948 !STRCMP(keywords
[i
+1], "mapper")
950 pU
->seqsetParams
.dwPort
=-1;/* FIXME:not sure*/
951 dwFlags
|= MCI_SEQ_SET_PORT
;
955 #define SII(str,flag,element) \
956 if (!STRCMP(keywords[i], str) && \
957 (i+1 < nrofkeywords)) { \
958 sscanf(keywords[i+1], "%ld", \
959 &(pU->seqsetParams.element));\
964 SII("tempo", MCI_SEQ_SET_TEMPO
, dwTempo
);
965 SII("port", MCI_SEQ_SET_PORT
, dwPort
);
966 SII("offset", MCI_SEQ_SET_PORT
, dwOffset
);
972 return MCIERR_MISSING_STRING_ARGUMENT
;
973 res
= mciSendCommandA(wDevID
, MCI_SET
, dwFlags
, (DWORD
)pU
);
980 * "off" disable break
981 * "on <keyid>" enable break on key with keyid
982 * (I strongly suspect, that there is another parameter:
984 * but I don't see it mentioned in my documentation.
988 MCISTR_Break(_MCISTR_PROTO_
)
990 LPMCI_BREAK_PARMS breakParams
= xmalloc(sizeof(MCI_BREAK_PARMS
));
993 if (!breakParams
) return 0;
995 breakParams
->dwCallback
= hwndCallback
;
996 /*breakParams.hwndBreak ? */
997 for (i
= 0; i
< nrofkeywords
; i
++) {
998 FLAG1("off", MCI_BREAK_OFF
);
999 if (!STRCMP(keywords
[i
], "on") && (nrofkeywords
> i
+1)) {
1000 dwFlags
&= ~MCI_BREAK_OFF
;
1001 dwFlags
|= MCI_BREAK_KEY
;
1002 sscanf(keywords
[i
+1], "%d", &(breakParams
->nVirtKey
));
1007 res
= mciSendCommandA(wDevID
, MCI_BREAK
, dwFlags
, (DWORD
)breakParams
);
1012 #define ITEM1(str, item, xtype) \
1013 if (!STRCMP(keywords[i], str)) { \
1014 gdcParams->dwItem = item; \
1019 #define ITEM2(str1, str2, item, xtype) \
1020 if ( !STRCMP(keywords[i], str1) && \
1021 (i+1 < nrofkeywords) && \
1022 !STRCMP(keywords[i+1], str2)) { \
1023 gdcParams->dwItem = item; \
1028 #define ITEM3(str1, str2, str3, item, xtype) \
1029 if ( !STRCMP(keywords[i], str1) && \
1030 (i+2 < nrofkeywords) && \
1031 !STRCMP(keywords[i+1], str2) && \
1032 !STRCMP(keywords[i+2], str3)) { \
1033 gdcParams->dwItem = item; \
1039 /* get device capabilities of MCI drivers
1042 * "device type" returns device name as string
1043 * "has audio" returns bool
1044 * "has video" returns bool
1045 * "uses files" returns bool
1046 * "compound device" returns bool
1047 * "can record" returns bool
1048 * "can play" returns bool
1049 * "can eject" returns bool
1050 * "can save" returns bool
1052 * "palettes" returns nr of available palette entries
1053 * "windows" returns nr of available windows
1054 * "can reverse" returns bool
1055 * "can stretch" returns bool
1056 * "slow play rate" returns the slow playrate
1057 * "fast play rate" returns the fast playrate
1058 * "normal play rate" returns the normal playrate
1060 * "can freeze" returns bool
1061 * "can lock" returns bool
1062 * "can reverse" returns bool
1063 * "can stretch" returns bool
1064 * "can stretch input" returns bool
1065 * "can test" returns bool
1066 * "has still" returns bool
1067 * "maximum play rate" returns the maximum play rate, in fps
1068 * "minimum play rate" returns the minimum play rate, in fps
1069 * "uses files" returns bool
1070 * "uses palettes" returns bool
1071 * "windows" returns nr of available windows
1073 * "windows" returns nr of available windows
1074 * "can stretch" returns bool
1075 * "can freeze" returns bool
1077 * "cav" assume CAV discs (default if no disk inserted)
1078 * "clv" assume CLV discs
1079 * "can reverse" returns bool
1080 * "slow play rate" returns the slow playrate
1081 * "fast play rate" returns the fast playrate
1082 * "normal play rate" returns the normal playrate
1084 * "inputs" returns nr of inputdevices
1085 * "outputs" returns nr of outputdevices
1088 MCISTR_Capability(_MCISTR_PROTO_
) {
1089 MCI_GETDEVCAPS_PARMS
*gdcParams
= xmalloc(sizeof(MCI_GETDEVCAPS_PARMS
));
1092 gdcParams
->dwCallback
= hwndCallback
;
1094 return MCIERR_MISSING_STRING_ARGUMENT
;
1095 /* well , thats default */
1096 dwFlags
|= MCI_GETDEVCAPS_ITEM
;
1097 gdcParams
->dwItem
= 0;
1099 for (i
= 0; i
< nrofkeywords
; i
++) {
1100 ITEM2("device", "type", MCI_GETDEVCAPS_DEVICE_TYPE
, _MCISTR_devtype
);
1101 ITEM2("has", "audio", MCI_GETDEVCAPS_HAS_AUDIO
, _MCISTR_bool
);
1102 ITEM2("has", "video", MCI_GETDEVCAPS_HAS_VIDEO
, _MCISTR_bool
);
1103 ITEM2("uses", "files", MCI_GETDEVCAPS_USES_FILES
, _MCISTR_bool
);
1104 ITEM2("compound", "device", MCI_GETDEVCAPS_COMPOUND_DEVICE
, _MCISTR_bool
);
1105 ITEM2("can", "record", MCI_GETDEVCAPS_CAN_RECORD
, _MCISTR_bool
);
1106 ITEM2("can", "play", MCI_GETDEVCAPS_CAN_PLAY
, _MCISTR_bool
);
1107 ITEM2("can", "eject", MCI_GETDEVCAPS_CAN_EJECT
, _MCISTR_bool
);
1108 ITEM2("can", "save", MCI_GETDEVCAPS_CAN_SAVE
, _MCISTR_bool
);
1110 case MCI_DEVTYPE_ANIMATION
:
1111 ITEM1("palettes", MCI_ANIM_GETDEVCAPS_PALETTES
, _MCISTR_int
);
1112 ITEM1("windows", MCI_ANIM_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1113 ITEM2("can", "reverse", MCI_ANIM_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1114 ITEM2("can", "stretch", MCI_ANIM_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1115 ITEM3("slow", "play", "rate", MCI_ANIM_GETDEVCAPS_SLOW_RATE
, _MCISTR_int
);
1116 ITEM3("fast", "play", "rate", MCI_ANIM_GETDEVCAPS_FAST_RATE
, _MCISTR_int
);
1117 ITEM3("normal", "play", "rate", MCI_ANIM_GETDEVCAPS_NORMAL_RATE
, _MCISTR_int
);
1119 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1120 ITEM2("can", "freeze", MCI_DGV_GETDEVCAPS_CAN_FREEZE
, _MCISTR_bool
);
1121 ITEM2("can", "lock", MCI_DGV_GETDEVCAPS_CAN_LOCK
, _MCISTR_bool
);
1122 ITEM2("can", "reverse", MCI_DGV_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1123 ITEM3("can", "stretch", "input", MCI_DGV_GETDEVCAPS_CAN_STR_IN
, _MCISTR_bool
);
1124 ITEM2("can", "stretch", MCI_DGV_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1125 ITEM2("can", "test", MCI_DGV_GETDEVCAPS_CAN_TEST
, _MCISTR_bool
);
1126 ITEM2("has", "still", MCI_DGV_GETDEVCAPS_HAS_STILL
, _MCISTR_bool
);
1127 ITEM3("maximum", "play", "rate", MCI_DGV_GETDEVCAPS_MAXIMUM_RATE
, _MCISTR_int
);
1128 ITEM3("minimum", "play", "rate", MCI_DGV_GETDEVCAPS_MINIMUM_RATE
, _MCISTR_int
);
1129 ITEM2("uses", "files", MCI_GETDEVCAPS_USES_FILES
, _MCISTR_bool
);
1130 ITEM2("uses", "palettes", MCI_DGV_GETDEVCAPS_PALETTES
, _MCISTR_bool
);
1131 ITEM1("windows", MCI_DGV_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1133 case MCI_DEVTYPE_OVERLAY
:
1134 ITEM1("windows", MCI_OVLY_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1135 ITEM2("can", "freeze", MCI_OVLY_GETDEVCAPS_CAN_FREEZE
, _MCISTR_bool
);
1136 ITEM2("can", "stretch", MCI_OVLY_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1138 case MCI_DEVTYPE_VIDEODISC
:
1139 FLAG1("cav", MCI_VD_GETDEVCAPS_CAV
);
1140 FLAG1("clv", MCI_VD_GETDEVCAPS_CLV
);
1141 ITEM2("can", "reverse", MCI_VD_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1142 ITEM3("slow", "play", "rate", MCI_VD_GETDEVCAPS_SLOW_RATE
, _MCISTR_int
);
1143 ITEM3("fast", "play", "rate", MCI_VD_GETDEVCAPS_FAST_RATE
, _MCISTR_int
);
1144 ITEM3("normal", "play", "rate", MCI_VD_GETDEVCAPS_NORMAL_RATE
, _MCISTR_int
);
1146 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
1147 ITEM1("inputs", MCI_WAVE_GETDEVCAPS_INPUTS
, _MCISTR_int
);
1148 ITEM1("outputs", MCI_WAVE_GETDEVCAPS_OUTPUTS
, _MCISTR_int
);
1152 res
= mciSendCommandA(wDevID
, MCI_GETDEVCAPS
, dwFlags
, (DWORD
)gdcParams
);
1154 /* no timeformat needed */
1156 _MCISTR_convreturn(type
, gdcParams
->dwReturn
, lpstrReturnString
,
1157 uReturnLength
, uDevTyp
, 0);
1164 /* resumes operation of device. no arguments, no return values */
1166 MCISTR_Resume(_MCISTR_PROTO_
)
1168 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1171 genParams
->dwCallback
= hwndCallback
;
1172 res
= mciSendCommandA(wDevID
, MCI_RESUME
, dwFlags
, (DWORD
)genParams
);
1177 /* pauses operation of device. no arguments, no return values */
1179 MCISTR_Pause(_MCISTR_PROTO_
)
1181 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1184 genParams
->dwCallback
= hwndCallback
;
1185 res
= mciSendCommandA(wDevID
, MCI_PAUSE
, dwFlags
, (DWORD
)genParams
);
1190 /* stops operation of device. no arguments, no return values */
1192 MCISTR_Stop(_MCISTR_PROTO_
)
1194 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1197 genParams
->dwCallback
= hwndCallback
;
1198 res
= mciSendCommandA(wDevID
, MCI_STOP
, dwFlags
, (DWORD
)genParams
);
1203 /* starts recording.
1205 * "overwrite" overwrite existing things
1206 * "insert" insert at current position
1207 * "to <time>" record up to <time> (specified in timeformat)
1208 * "from <time>" record from <time> (specified in timeformat)
1211 MCISTR_Record(_MCISTR_PROTO_
) {
1212 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1214 MCI_RECORD_PARMS
*recordParams
= xmalloc(sizeof(MCI_RECORD_PARMS
));
1216 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1217 if (res
) return res
;
1220 case MCI_FORMAT_MILLISECONDS
:
1221 case MCI_FORMAT_FRAMES
:
1222 case MCI_FORMAT_BYTES
:
1223 case MCI_FORMAT_SAMPLES
:
1227 case MCI_FORMAT_HMS
:
1228 case MCI_FORMAT_MSF
:
1229 parsestr
="%d:%d:%d";
1232 case MCI_FORMAT_TMSF
:
1233 parsestr
="%d:%d:%d:%d";
1236 default:FIXME(mci
, "unknown timeformat %d, please report.\n", timef
);
1241 recordParams
->dwCallback
= hwndCallback
;
1242 for (i
= 0; i
< nrofkeywords
; ) {
1243 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1245 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1246 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1247 /* add up all integers we got, if we have more
1248 * shift them. (Well I should use the macros in
1249 * mmsystem.h, right).
1251 recordParams
->dwTo
= 0;
1252 for (k
= 0; k
< j
; k
++)
1253 recordParams
->dwTo
+= a
[k
] << (8*(nrargs
-k
));
1257 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1258 dwFlags
|= MCI_FROM
;
1259 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1260 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1262 recordParams
->dwFrom
= 0;
1263 for (k
= 0; k
< j
; k
++)
1264 recordParams
->dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1268 FLAG1("insert", MCI_RECORD_INSERT
);
1269 FLAG1("overwrite", MCI_RECORD_OVERWRITE
);
1272 res
= mciSendCommandA(wDevID
, MCI_RECORD
, dwFlags
, (DWORD
)recordParams
);
1279 * "to <time>" play up to <time> (specified in set timeformat)
1280 * "from <time>" play from <time> (specified in set timeformat)
1284 * "scan" play as fast as possible (with audio disabled perhaps)
1285 * "reverse" play reverse
1286 * "speed <fps>" play with specified frames per second
1290 * "scan" play as fast as possible (with audio disabled perhaps)
1291 * "reverse" play reverse
1292 * "speed <fps>" play with specified frames per second
1300 MCISTR_Play(_MCISTR_PROTO_
) {
1301 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1304 MCI_PLAY_PARMS playParams
;
1305 MCI_VD_PLAY_PARMS vdplayParams
;
1306 MCI_ANIM_PLAY_PARMS animplayParams
;
1307 MCI_DGV_PLAY_PARMS dgvplayParams
;
1309 union U
*pU
= xmalloc(sizeof(union U
));
1311 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1312 if (res
) return res
;
1314 case MCI_FORMAT_MILLISECONDS
:
1315 case MCI_FORMAT_FRAMES
:
1316 case MCI_FORMAT_BYTES
:
1317 case MCI_FORMAT_SAMPLES
:
1321 case MCI_FORMAT_HMS
:
1322 case MCI_FORMAT_MSF
:
1323 parsestr
="%d:%d:%d";
1326 case MCI_FORMAT_TMSF
:
1327 parsestr
="%d:%d:%d:%d";
1330 default:FIXME(mci
, "unknown timeformat %d, please report.\n", timef
);
1335 pU
->playParams
.dwCallback
= hwndCallback
;
1336 for (i
= 0; i
< nrofkeywords
; ) {
1337 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1339 a
[0]=a
[1]=a
[2]=a
[3]=0;
1340 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1341 /* add up all integers we got, if we have more
1342 * shift them. (Well I should use the macros in
1343 * mmsystem.h, right).
1345 pU
->playParams
.dwTo
=0;
1346 for (k
= 0; k
< j
; k
++)
1347 pU
->playParams
.dwTo
+= a
[k
] << (8*(nrargs
-k
));
1351 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1352 dwFlags
|= MCI_FROM
;
1353 a
[0]=a
[1]=a
[2]=a
[3]=0;
1354 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1356 pU
->playParams
.dwFrom
=0;
1357 for (k
= 0; k
< j
; k
++)
1358 pU
->playParams
.dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1363 case MCI_DEVTYPE_VIDEODISC
:
1364 FLAG1("slow", MCI_VD_PLAY_SLOW
);
1365 FLAG1("fast", MCI_VD_PLAY_FAST
);
1366 FLAG1("scan", MCI_VD_PLAY_SCAN
);
1367 FLAG1("reverse", MCI_VD_PLAY_REVERSE
);
1368 if (!STRCMP(keywords
[i
], "speed") && (i
+1 < nrofkeywords
)) {
1369 dwFlags
|= MCI_VD_PLAY_SPEED
;
1370 sscanf(keywords
[i
+1], "%ld", &(pU
->vdplayParams
.dwSpeed
));
1375 case MCI_DEVTYPE_ANIMATION
:
1376 FLAG1("slow", MCI_ANIM_PLAY_SLOW
);
1377 FLAG1("fast", MCI_ANIM_PLAY_FAST
);
1378 FLAG1("scan", MCI_ANIM_PLAY_SCAN
);
1379 FLAG1("reverse", MCI_ANIM_PLAY_REVERSE
);
1380 if (!STRCMP(keywords
[i
], "speed") && (i
+1 < nrofkeywords
)) {
1381 dwFlags
|= MCI_ANIM_PLAY_SPEED
;
1382 sscanf(keywords
[i
+1], "%ld", &(pU
->animplayParams
.dwSpeed
));
1387 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1388 /* EPP FLAG1("fullscreen", MCI_MCIAVI_PLAY_FULLSCREEN); */
1389 FLAG1("repeat", MCI_DGV_PLAY_REPEAT
);
1390 FLAG1("reverse", MCI_DGV_PLAY_REVERSE
);
1391 /* EPP FLAG1("window", MCI_MCIAVI_PLAY_WINDOW); */
1396 res
= mciSendCommandA(wDevID
, MCI_PLAY
, dwFlags
, (DWORD
)pU
);
1401 /* seek to a specified position
1403 * "to start" seek to start of medium
1404 * "to end" seek to end of medium
1405 * "to <time>" seek to <time> specified in current timeformat
1408 MCISTR_Seek(_MCISTR_PROTO_
) {
1409 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1411 MCI_SEEK_PARMS
*seekParams
= xmalloc(sizeof(MCI_SEEK_PARMS
));
1413 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1414 if (res
) return res
;
1416 case MCI_FORMAT_MILLISECONDS
:
1417 case MCI_FORMAT_FRAMES
:
1418 case MCI_FORMAT_BYTES
:
1419 case MCI_FORMAT_SAMPLES
:
1423 case MCI_FORMAT_HMS
:
1424 case MCI_FORMAT_MSF
:
1425 parsestr
="%d:%d:%d";
1428 case MCI_FORMAT_TMSF
:
1429 parsestr
="%d:%d:%d:%d";
1433 FIXME(mci
, "unknown timeformat %d, please report.\n", timef
);
1438 seekParams
->dwCallback
= hwndCallback
;
1439 for (i
= 0; i
< nrofkeywords
; ) {
1440 if (!STRCMP(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1441 if (!STRCMP(keywords
[i
+1], "start")) {
1442 dwFlags
|= MCI_SEEK_TO_START
;
1443 seekParams
->dwTo
= 0;
1447 if (!STRCMP(keywords
[i
+1], "end")) {
1448 dwFlags
|= MCI_SEEK_TO_END
;
1449 seekParams
->dwTo
= 0;
1455 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1456 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1457 seekParams
->dwTo
= 0;
1458 for (k
= 0; k
< j
; k
++)
1459 seekParams
->dwTo
+= a
[k
] << (8*(nrargs
-k
));
1463 case MCI_DEVTYPE_VIDEODISC
:
1464 FLAG1("reverse", MCI_VD_SEEK_REVERSE
);
1469 res
= mciSendCommandA(wDevID
, MCI_SEEK
, dwFlags
, (DWORD
)seekParams
);
1474 /* close media/driver */
1476 MCISTR_Close(_MCISTR_PROTO_
)
1478 MCI_GENERIC_PARMS
* closeParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1481 closeParams
->dwCallback
= hwndCallback
;
1482 res
= mciSendCommandA(wDevID
, MCI_CLOSE
, dwFlags
, (DWORD
)closeParams
);
1487 /* return information.
1489 * "product" return product name (human readable)
1490 * "file" return filename
1492 * "text" returns text?
1494 * "text" returns text?
1507 MCISTR_Info(_MCISTR_PROTO_
)
1510 MCI_INFO_PARMSA infoParams
;
1511 MCI_DGV_INFO_PARMSA dgvinfoParams
;
1513 union U
* pU
= xmalloc(sizeof(union U
));
1518 for (i
= 0; i
< nrofkeywords
; i
++) {
1519 FLAG1("product", MCI_INFO_PRODUCT
);
1520 FLAG1("file", MCI_INFO_FILE
);
1522 case MCI_DEVTYPE_ANIMATION
:
1523 FLAG2("window", "text", MCI_ANIM_INFO_TEXT
);
1525 case MCI_DEVTYPE_OVERLAY
:
1526 FLAG2("window", "text", MCI_OVLY_INFO_TEXT
);
1528 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1529 #define MI1(str, flag) \
1530 if (!STRCMP(keywords[i], str)) { \
1531 dwFlags |= MCI_DGV_INFO_ITEM; \
1532 pU->dgvinfoParams.dwItem |= flag; \
1536 #define MI2(str1, str2, flag) \
1537 if (!STRCMP(keywords[i], str1) && \
1538 (i+1 < nrofkeywords) && \
1539 !STRCMP(keywords[i+1], str2)) { \
1540 dwFlags |= MCI_DGV_INFO_ITEM; \
1541 pU->dgvinfoParams.dwItem |= flag; \
1545 MI2("audio", "algorithm", MCI_DGV_INFO_AUDIO_ALG
);
1546 MI2("audio", "quality", MCI_DGV_INFO_AUDIO_QUALITY
);
1547 MI2("still", "algorithm", MCI_DGV_INFO_STILL_ALG
);
1548 MI2("still", "quality", MCI_DGV_INFO_STILL_QUALITY
);
1549 MI1("usage", MCI_DGV_INFO_USAGE
);
1550 MI1("version", MCI_INFO_VERSION
);
1551 MI2("video", "algorithm", MCI_DGV_INFO_VIDEO_ALG
);
1552 MI2("video", "quality", MCI_DGV_INFO_VIDEO_QUALITY
);
1553 MI2("window", "text", MCI_DGV_INFO_TEXT
);
1558 if (dwFlags
== sflags
)
1559 return MCIERR_MISSING_STRING_ARGUMENT
;
1560 pU
->infoParams
.dwCallback
= hwndCallback
;
1562 /* MCI driver will fill in lpstrReturn, dwRetSize.
1563 * FIXME: I don't know if this is correct behaviour
1565 res
= mciSendCommandA(wDevID
, MCI_INFO
, dwFlags
, (DWORD
)pU
);
1567 _MCI_STR(pU
->infoParams
.lpstrReturn
);
1572 /* query MCI driver itself for information
1574 * "installname" return install name of <device> (system.ini)
1575 * "quantity" return nr of installed drivers
1576 * "open" open drivers only (additional flag)
1577 * "name <nr>" return nr of devices with <devicetyp>
1578 * "name all" return nr of all devices
1582 MCISTR_Sysinfo(_MCISTR_PROTO_
) {
1583 MCI_SYSINFO_PARMSA sysinfoParams
;
1586 sysinfoParams
.lpstrReturn
= lpstrReturnString
;
1587 sysinfoParams
.dwRetSize
= uReturnLength
;
1588 sysinfoParams
.wDeviceType
= uDevTyp
;
1589 sysinfoParams
.dwCallback
= hwndCallback
;
1591 for (i
= 0; i
< nrofkeywords
; i
++) {
1592 FLAG1("installname", MCI_SYSINFO_INSTALLNAME
);
1593 FLAG1("quantity", MCI_SYSINFO_INSTALLNAME
);
1594 FLAG1("open", MCI_SYSINFO_OPEN
);
1595 if (!strcmp(keywords
[i
], "name") && (i
+1 < nrofkeywords
)) {
1596 sscanf(keywords
[i
+1], "%ld", &(sysinfoParams
.dwNumber
));
1597 dwFlags
|= MCI_SYSINFO_NAME
;
1601 res
= mciSendCommandA(0, MCI_SYSINFO
, dwFlags
, (DWORD
)&sysinfoParams
);
1603 if (dwFlags
& MCI_SYSINFO_QUANTITY
) {
1606 sprintf(buf
, "%ld", *(long*)lpstrReturnString
);
1609 /* no need to copy anything back, mciSysInfo did it for us */
1614 * Argument: "<filename>"
1615 * Overlay: "at <left> <top> <right> <bottom>" additional
1618 MCISTR_Load(_MCISTR_PROTO_
) {
1620 MCI_LOAD_PARMSA loadParams
;
1621 MCI_OVLY_LOAD_PARMSA ovlyloadParams
;
1623 union U
*pU
= xmalloc(sizeof(union U
));
1624 int i
, len
= 0, res
;
1627 for (i
= 0; i
< nrofkeywords
; ) {
1629 case MCI_DEVTYPE_OVERLAY
:
1630 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1631 dwFlags
|= MCI_OVLY_RECT
;
1632 sscanf(keywords
[i
+1], "%d", &(pU
->ovlyloadParams
.rc
.left
));
1633 sscanf(keywords
[i
+2], "%d", &(pU
->ovlyloadParams
.rc
.top
));
1634 sscanf(keywords
[i
+3], "%d", &(pU
->ovlyloadParams
.rc
.right
));
1635 sscanf(keywords
[i
+4], "%d", &(pU
->ovlyloadParams
.rc
.bottom
));
1636 memcpy(keywords
+i
, keywords
+(i
+5), nrofkeywords
-(i
+5));
1641 len
+= strlen(keywords
[i
])+1;
1644 s
=(char*)xmalloc(len
);
1646 while (i
< nrofkeywords
) {
1647 strcat(s
, keywords
[i
]);
1649 if (i
< nrofkeywords
) strcat(s
, " ");
1651 pU
->loadParams
.lpfilename
= s
;
1652 pU
->loadParams
.dwCallback
= hwndCallback
;
1653 dwFlags
|= MCI_LOAD_FILE
;
1654 res
= mciSendCommandA(wDevID
, MCI_LOAD
, dwFlags
, (DWORD
)pU
);
1661 * Argument: "<filename>"
1662 * Overlay: "at <left> <top> <right> <bottom>" additional
1665 MCISTR_Save(_MCISTR_PROTO_
) {
1667 MCI_SAVE_PARMS saveParams
;
1668 MCI_OVLY_SAVE_PARMSA ovlysaveParams
;
1670 union U
* pU
= xmalloc(sizeof(union U
));
1671 int i
, len
= 0, res
;
1674 for (i
= 0; i
< nrofkeywords
; ) {
1676 case MCI_DEVTYPE_OVERLAY
:
1677 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1678 dwFlags
|= MCI_OVLY_RECT
;
1679 sscanf(keywords
[i
+1], "%d", &(pU
->ovlysaveParams
.rc
.left
));
1680 sscanf(keywords
[i
+2], "%d", &(pU
->ovlysaveParams
.rc
.top
));
1681 sscanf(keywords
[i
+3], "%d", &(pU
->ovlysaveParams
.rc
.right
));
1682 sscanf(keywords
[i
+4], "%d", &(pU
->ovlysaveParams
.rc
.bottom
));
1683 memcpy(keywords
+i
, keywords
+(i
+5), nrofkeywords
-(i
+5));
1688 len
+= strlen(keywords
[i
])+1;
1691 s
= (char*)xmalloc(len
);
1693 while (i
< nrofkeywords
) {
1694 strcat(s
, keywords
[i
]);
1696 if (i
< nrofkeywords
) strcat(s
, " ");
1698 pU
->saveParams
.lpfilename
= s
;
1699 pU
->saveParams
.dwCallback
= hwndCallback
;
1700 dwFlags
|= MCI_LOAD_FILE
;
1701 res
= mciSendCommandA(wDevID
, MCI_SAVE
, dwFlags
, (DWORD
)pU
);
1707 /* prepare device for input/output
1708 * (only applyable to waveform audio)
1711 MCISTR_Cue(_MCISTR_PROTO_
) {
1712 MCI_GENERIC_PARMS
*cueParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1715 for (i
= 0; i
< nrofkeywords
; i
++) {
1717 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
1718 FLAG1("input", MCI_WAVE_INPUT
);
1719 FLAG1("output", MCI_WAVE_OUTPUT
);
1724 cueParams
->dwCallback
= hwndCallback
;
1726 res
= mciSendCommandA(wDevID
, MCI_CUE
, dwFlags
, (DWORD
)cueParams
);
1731 /* delete information */
1733 MCISTR_Delete(_MCISTR_PROTO_
) {
1734 int timef
, nrargs
, i
, j
, k
, a
[4], res
;
1736 MCI_WAVE_DELETE_PARMS
*deleteParams
= xmalloc(sizeof(MCI_WAVE_DELETE_PARMS
));
1738 /* only implemented for waveform audio */
1739 if (uDevTyp
!= MCI_DEVTYPE_WAVEFORM_AUDIO
)
1740 return MCIERR_UNSUPPORTED_FUNCTION
; /* well it fits */
1741 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1742 if (res
) return res
;
1744 case MCI_FORMAT_MILLISECONDS
:
1745 case MCI_FORMAT_FRAMES
:
1746 case MCI_FORMAT_BYTES
:
1747 case MCI_FORMAT_SAMPLES
:
1751 case MCI_FORMAT_HMS
:
1752 case MCI_FORMAT_MSF
:
1753 parsestr
="%d:%d:%d";
1756 case MCI_FORMAT_TMSF
:
1757 parsestr
="%d:%d:%d:%d";
1760 default:FIXME(mci
, "unknown timeformat %d, please report.\n", timef
);
1765 for (i
= 0; i
< nrofkeywords
; ) {
1766 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1768 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1769 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1770 /* add up all integers we got, if we have more
1771 * shift them. (Well I should use the macros in
1772 * mmsystem.h, right).
1774 deleteParams
->dwTo
= 0;
1775 for (k
= 0;k
< j
;k
++)
1776 deleteParams
->dwTo
+= a
[k
]<<(8*(nrargs
-k
));
1780 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1781 dwFlags
|= MCI_FROM
;
1782 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1783 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1785 deleteParams
->dwFrom
= 0;
1786 for (k
= 0; k
< j
; k
++)
1787 deleteParams
->dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1793 deleteParams
->dwCallback
= hwndCallback
;
1794 res
= mciSendCommandA(wDevID
, MCI_DELETE
, dwFlags
, (DWORD
)deleteParams
);
1799 /* send command to device. only applies to videodisc */
1801 MCISTR_Escape(_MCISTR_PROTO_
)
1803 LPMCI_VD_ESCAPE_PARMSA escapeParams
= xmalloc(sizeof(MCI_VD_ESCAPE_PARMSA
));
1804 int i
, len
= 0, res
;
1807 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
1808 return MCIERR_UNSUPPORTED_FUNCTION
;
1810 for (i
= 0; i
< nrofkeywords
; i
++) {
1811 len
+= strlen(keywords
[i
]) + 1;
1813 s
= (char*)malloc(len
);
1815 for (i
= 0; i
< nrofkeywords
; ) {
1816 strcat(s
, keywords
[i
]);
1818 if (i
< nrofkeywords
) strcat(s
, " ");
1820 escapeParams
->lpstrCommand
= s
;
1821 escapeParams
->dwCallback
= hwndCallback
;
1822 dwFlags
|= MCI_VD_ESCAPE_STRING
;
1823 res
= mciSendCommandA(wDevID
, MCI_ESCAPE
, dwFlags
, (DWORD
)escapeParams
);
1829 /* unfreeze [part of] the overlayed video
1830 * only applyable to Overlay devices
1833 MCISTR_Unfreeze(_MCISTR_PROTO_
)
1835 LPMCI_OVLY_RECT_PARMS unfreezeParams
= xmalloc(sizeof(MCI_OVLY_RECT_PARMS
));
1838 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1839 return MCIERR_UNSUPPORTED_FUNCTION
;
1840 for (i
= 0; i
< nrofkeywords
; ) {
1841 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1842 sscanf(keywords
[i
+1], "%d", &(unfreezeParams
->rc
.left
));
1843 sscanf(keywords
[i
+2], "%d", &(unfreezeParams
->rc
.top
));
1844 sscanf(keywords
[i
+3], "%d", &(unfreezeParams
->rc
.right
));
1845 sscanf(keywords
[i
+4], "%d", &(unfreezeParams
->rc
.bottom
));
1846 dwFlags
|= MCI_OVLY_RECT
;
1852 unfreezeParams
->dwCallback
= hwndCallback
;
1853 res
= mciSendCommandA(wDevID
, MCI_UNFREEZE
, dwFlags
, (DWORD
)unfreezeParams
);
1854 free(unfreezeParams
);
1857 /* freeze [part of] the overlayed video
1858 * only applyable to Overlay devices
1861 MCISTR_Freeze(_MCISTR_PROTO_
)
1863 LPMCI_OVLY_RECT_PARMS freezeParams
= xmalloc(sizeof(MCI_OVLY_RECT_PARMS
));
1866 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1867 return MCIERR_UNSUPPORTED_FUNCTION
;
1868 for (i
= 0; i
< nrofkeywords
; ) {
1869 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1870 sscanf(keywords
[i
+1], "%d", &(freezeParams
->rc
.left
));
1871 sscanf(keywords
[i
+2], "%d", &(freezeParams
->rc
.top
));
1872 sscanf(keywords
[i
+3], "%d", &(freezeParams
->rc
.right
));
1873 sscanf(keywords
[i
+4], "%d", &(freezeParams
->rc
.bottom
));
1874 dwFlags
|= MCI_OVLY_RECT
;
1880 freezeParams
->dwCallback
= hwndCallback
;
1881 res
= mciSendCommandA(wDevID
, MCI_FREEZE
, dwFlags
, (DWORD
)freezeParams
);
1886 /* copy parts of image to somewhere else
1887 * "source [at <left> <top> <right> <bottom>]" source is framebuffer [or rect]
1888 * "destination [at <left> <top> <right> <bottom>]" destination is framebuffer [or rect]
1890 * "frame [at <left> <top> <right> <bottom>]" frame is framebuffer [or rect]
1891 * where the video input is placed
1892 * "video [at <left> <top> <right> <bottom>]" video is whole video [or rect]
1893 * (defining part of input to
1895 * FIXME: This whole junk is passing multiple rectangles.
1896 * I don't know how to do that with the present interface.
1897 * (Means code below is broken)
1900 MCISTR_Put(_MCISTR_PROTO_
) {
1902 MCI_OVLY_RECT_PARMS ovlyputParams
;
1903 MCI_ANIM_RECT_PARMS animputParams
;
1904 MCI_DGV_RECT_PARMS dgvputParams
;
1906 union U
* pU
= xmalloc(sizeof(union U
));
1909 for (i
= 0; i
< nrofkeywords
; ) {
1911 case MCI_DEVTYPE_ANIMATION
:
1912 FLAG1("source", MCI_ANIM_PUT_SOURCE
);
1913 FLAG1("destination", MCI_ANIM_PUT_DESTINATION
);
1914 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1915 sscanf(keywords
[i
+1], "%d", &(pU
->animputParams
.rc
.left
));
1916 sscanf(keywords
[i
+2], "%d", &(pU
->animputParams
.rc
.top
));
1917 sscanf(keywords
[i
+3], "%d", &(pU
->animputParams
.rc
.right
));
1918 sscanf(keywords
[i
+4], "%d", &(pU
->animputParams
.rc
.bottom
));
1919 dwFlags
|= MCI_ANIM_RECT
;
1924 case MCI_DEVTYPE_OVERLAY
:
1925 FLAG1("source", MCI_OVLY_PUT_SOURCE
);
1926 FLAG1("destination", MCI_OVLY_PUT_DESTINATION
);
1927 FLAG1("video", MCI_OVLY_PUT_VIDEO
);
1928 FLAG1("frame", MCI_OVLY_PUT_FRAME
);
1929 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1930 sscanf(keywords
[i
+1], "%d", &(pU
->ovlyputParams
.rc
.left
));
1931 sscanf(keywords
[i
+2], "%d", &(pU
->ovlyputParams
.rc
.top
));
1932 sscanf(keywords
[i
+3], "%d", &(pU
->ovlyputParams
.rc
.right
));
1933 sscanf(keywords
[i
+4], "%d", &(pU
->ovlyputParams
.rc
.bottom
));
1934 dwFlags
|= MCI_OVLY_RECT
;
1939 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1940 FLAG1("source", MCI_DGV_PUT_SOURCE
);
1941 FLAG1("destination", MCI_DGV_PUT_DESTINATION
);
1942 FLAG1("video", MCI_DGV_PUT_VIDEO
);
1943 FLAG1("frame", MCI_DGV_PUT_FRAME
);
1944 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1945 sscanf(keywords
[i
+1], "%d", &(pU
->dgvputParams
.rc
.left
));
1946 sscanf(keywords
[i
+2], "%d", &(pU
->dgvputParams
.rc
.top
));
1947 sscanf(keywords
[i
+3], "%d", &(pU
->dgvputParams
.rc
.right
));
1948 sscanf(keywords
[i
+4], "%d", &(pU
->dgvputParams
.rc
.bottom
));
1949 dwFlags
|= MCI_DGV_RECT
;
1958 pU
->dgvputParams
.dwCallback
= hwndCallback
;
1959 res
= mciSendCommandA(wDevID
, MCI_PUT
, dwFlags
, (DWORD
)pU
);
1964 /* palette behaviour changing
1966 * "normal" realize the palette normally
1967 * "background" realize the palette as background palette
1970 MCISTR_Realize(_MCISTR_PROTO_
)
1972 MCI_GENERIC_PARMS
*realizeParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1975 if (uDevTyp
!= MCI_DEVTYPE_ANIMATION
)
1976 return MCIERR_UNSUPPORTED_FUNCTION
;
1977 for (i
= 0; i
< nrofkeywords
; i
++) {
1978 FLAG1("background", MCI_ANIM_REALIZE_BKGD
);
1979 FLAG1("normal", MCI_ANIM_REALIZE_NORM
);
1981 realizeParams
->dwCallback
= hwndCallback
;
1982 res
= mciSendCommandA(wDevID
, MCI_REALIZE
, dwFlags
, (DWORD
)realizeParams
);
1983 free(realizeParams
);
1988 * "algorithm <algorithm>"
1989 * "alignment to <integer>"
1990 * "bass to <factor>"
1991 * "bitspersample to <bit_count>"
1992 * "bytespersec to <integer>"
1997 * "left volume to <factor>"
2002 * "quality <descripto>r"
2007 * "right volume to <factor>"
2008 * "samplespersec to <integer>"
2009 * "source to <sourcename>"
2010 * "stream to <number>"
2011 * "treble to <factor>"
2012 * "volume to <factor>"
2016 * "monitor to type number number"
2018 * "record track track_number off"
2020 * "record track track_number on "
2021 * "source to type number number"
2022 * "track track_number off"
2023 * "track track_number on"
2026 MCISTR_SetAudio(_MCISTR_PROTO_
)
2028 MCI_DGV_SETAUDIO_PARMSA setaudioParams
;
2031 if (uDevTyp
!= MCI_DEVTYPE_DIGITAL_VIDEO
)
2032 return MCIERR_UNSUPPORTED_FUNCTION
;
2034 setaudioParams
.dwCallback
= hwndCallback
;
2036 for (i
= 0; i
< nrofkeywords
; ) {
2037 if (!STRCMP(keywords
[i
], "algorithm") && (i
+1 < nrofkeywords
)) {
2038 setaudioParams
.lpstrAlgorithm
= strdup(keywords
[i
+1]);
2039 dwFlags
|= MCI_DGV_SETAUDIO_ALG
;
2043 #define MSAI2(str1, str2, flag) \
2044 if ( !STRCMP(keywords[i], str1) && (i+2 < nrofkeywords) && \
2045 !STRCMP(keywords[i+1], str2)) { \
2046 dwFlags |= MCI_DGV_SETAUDIO_ITEM; \
2047 setaudioParams.dwItem = flag; \
2048 sscanf(keywords[i+2], "%lu", &setaudioParams.dwValue); \
2052 #define MSAI3(str1, str2, str3, flag) \
2053 if ( !STRCMP(keywords[i], str1) && (i+3 < nrofkeywords) && \
2054 !STRCMP(keywords[i+1], str2) && !STRCMP(keywords[i+2], str3)) { \
2055 dwFlags |= MCI_DGV_SETAUDIO_ITEM; \
2056 setaudioParams.dwItem = flag; \
2057 sscanf(keywords[i+3], "%lu", &setaudioParams.dwValue); \
2061 MSAI2("alignment", "to", MCI_DGV_SETAUDIO_BLOCKALIGN
);
2062 MSAI2("bass", "to", MCI_DGV_SETAUDIO_BASS
);
2063 MSAI2("bitspersample", "to", MCI_DGV_SETAUDIO_BITSPERSAMPLE
);
2064 MSAI2("bytespersec", "to", MCI_DGV_SETAUDIO_AVGBYTESPERSEC
);
2065 MSAI2("samplespersec", "to", MCI_DGV_SETAUDIO_SAMPLESPERSEC
);
2066 MSAI2("stream", "to", MCI_DGV_SETAUDIO_STREAM
);
2067 MSAI2("treble", "to", MCI_DGV_SETAUDIO_TREBLE
);
2068 MSAI2("volume", "to", MCI_DGV_SETAUDIO_VOLUME
);
2069 MSAI3("input", "bass", "to", MCI_DGV_SETAUDIO_BASS
|MCI_DGV_SETAUDIO_INPUT
);
2070 MSAI3("input", "treble", "to", MCI_DGV_SETAUDIO_TREBLE
|MCI_DGV_SETAUDIO_INPUT
);
2071 MSAI3("input", "volume", "to", MCI_DGV_SETAUDIO_VOLUME
|MCI_DGV_SETAUDIO_INPUT
);
2072 MSAI3("output", "bass", "to", MCI_DGV_SETAUDIO_BASS
|MCI_DGV_SETAUDIO_OUTPUT
);
2073 MSAI3("output", "treble", "to", MCI_DGV_SETAUDIO_TREBLE
|MCI_DGV_SETAUDIO_OUTPUT
);
2074 MSAI3("output", "volume", "to", MCI_DGV_SETAUDIO_VOLUME
|MCI_DGV_SETAUDIO_OUTPUT
);
2076 FLAG1("clocktime", MCI_DGV_SETAUDIO_CLOCKTIME
);
2077 FLAG2("left", "off", MCI_DGV_SETAUDIO_LEFT
|MCI_SET_OFF
);
2078 FLAG2("left", "on", MCI_DGV_SETAUDIO_LEFT
|MCI_SET_ON
);
2079 if (!STRCMP(keywords
[i
], "left") && (i
+3 < nrofkeywords
) &&
2080 !STRCMP(keywords
[i
+1], "volume") && !STRCMP(keywords
[i
+2], "to")) {
2081 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
| MCI_DGV_SETAUDIO_VALUE
| MCI_DGV_SETAUDIO_LEFT
;
2082 setaudioParams
.dwItem
= MCI_DGV_SETAUDIO_VOLUME
;
2083 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwValue
);
2087 FLAG1("off", MCI_SET_OFF
);
2088 FLAG1("on", MCI_SET_ON
);
2089 if (!STRCMP(keywords
[i
], "over") && (i
+1 < nrofkeywords
)) {
2090 dwFlags
|= MCI_DGV_SETAUDIO_OVER
;
2091 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwOver
);
2095 if (!STRCMP(keywords
[i
], "quality") && (i
+1 < nrofkeywords
)) {
2096 setaudioParams
.lpstrQuality
= strdup(keywords
[i
+1]);
2097 dwFlags
|= MCI_DGV_SETAUDIO_QUALITY
;
2101 FLAG2("record", "off", MCI_DGV_SETAUDIO_RECORD
|MCI_SET_OFF
);
2102 FLAG2("record", "on", MCI_DGV_SETAUDIO_RECORD
|MCI_SET_ON
);
2103 FLAG2("right", "off", MCI_DGV_SETAUDIO_RIGHT
|MCI_SET_OFF
);
2104 FLAG2("right", "on", MCI_DGV_SETAUDIO_RIGHT
|MCI_SET_ON
);
2105 if (!STRCMP(keywords
[i
], "right") && (i
+3 < nrofkeywords
) &&
2106 !STRCMP(keywords
[i
+1], "volume") && !STRCMP(keywords
[i
+2], "to")) {
2107 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
| MCI_DGV_SETAUDIO_VALUE
| MCI_DGV_SETAUDIO_RIGHT
;
2108 setaudioParams
.dwItem
= MCI_DGV_SETAUDIO_VOLUME
;
2109 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwValue
);
2113 if (!STRCMP(keywords
[i
], "source") && (i
+2 < nrofkeywords
) && !STRCMP(keywords
[i
+1], "to")) {
2114 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
;
2115 setaudioParams
.dwItem
|= MCI_DGV_SETAUDIO_SOURCE
;
2116 if (!STRCMP(keywords
[i
+2], "left")) {
2117 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_LEFT
;
2118 } else if (!STRCMP(keywords
[i
+2], "right")) {
2119 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_RIGHT
;
2120 } else if (!STRCMP(keywords
[i
+2], "average")) {
2121 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_AVERAGE
;
2122 } else if (!STRCMP(keywords
[i
+2], "stereo")) {
2123 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_STEREO
;
2125 res
= MCIERR_UNSUPPORTED_FUNCTION
;
2132 res
= mciSendCommandA(wDevID
, MCI_SETAUDIO
, dwFlags
, (DWORD
)&setaudioParams
);
2133 free(setaudioParams
.lpstrAlgorithm
);
2134 free(setaudioParams
.lpstrQuality
);
2138 /* videodisc spinning
2143 MCISTR_Spin(_MCISTR_PROTO_
)
2145 MCI_GENERIC_PARMS
*spinParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
2148 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
2149 return MCIERR_UNSUPPORTED_FUNCTION
;
2150 for (i
= 0; i
< nrofkeywords
; i
++) {
2151 FLAG1("up", MCI_VD_SPIN_UP
);
2152 FLAG1("down", MCI_VD_SPIN_UP
);
2154 spinParams
->dwCallback
= hwndCallback
;
2155 res
= mciSendCommandA(wDevID
, MCI_SPIN
, dwFlags
, (DWORD
)spinParams
);
2160 /* step single frames
2161 * "reverse" optional flag
2162 * "by <nr>" for <nr> frames
2165 MCISTR_Step(_MCISTR_PROTO_
) {
2167 MCI_ANIM_STEP_PARMS animstepParams
;
2168 MCI_VD_STEP_PARMS vdstepParams
;
2170 union U
*pU
= xmalloc(sizeof(union U
));
2173 for (i
= 0; i
< nrofkeywords
; ) {
2175 case MCI_DEVTYPE_ANIMATION
:
2176 FLAG1("reverse", MCI_ANIM_STEP_REVERSE
);
2177 if (!STRCMP(keywords
[i
], "by") && (i
+1 < nrofkeywords
)) {
2178 sscanf(keywords
[i
+1], "%ld", &(pU
->animstepParams
.dwFrames
));
2179 dwFlags
|= MCI_ANIM_STEP_FRAMES
;
2184 case MCI_DEVTYPE_VIDEODISC
:
2185 FLAG1("reverse", MCI_VD_STEP_REVERSE
);
2186 if (!STRCMP(keywords
[i
], "by") && (i
+1 < nrofkeywords
)) {
2187 sscanf(keywords
[i
+1], "%ld", &(pU
->vdstepParams
.dwFrames
));
2188 dwFlags
|= MCI_VD_STEP_FRAMES
;
2196 pU
->animstepParams
.dwCallback
= hwndCallback
;
2197 res
= mciSendCommandA(wDevID
, MCI_STEP
, dwFlags
, (DWORD
)pU
);
2202 /* update animation window
2204 * "at <left> <top> <right> <bottom>" only in this rectangle
2205 * "hdc" device context
2208 MCISTR_Update(_MCISTR_PROTO_
) {
2210 LPMCI_ANIM_UPDATE_PARMS updateParams
= xmalloc(sizeof(MCI_ANIM_UPDATE_PARMS
));
2212 for (i
= 0; i
< nrofkeywords
; ) {
2213 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
2214 sscanf(keywords
[i
+1], "%d", &(updateParams
->rc
.left
));
2215 sscanf(keywords
[i
+2], "%d", &(updateParams
->rc
.top
));
2216 sscanf(keywords
[i
+3], "%d", &(updateParams
->rc
.right
));
2217 sscanf(keywords
[i
+4], "%d", &(updateParams
->rc
.bottom
));
2218 dwFlags
|= MCI_ANIM_RECT
;
2222 if (!STRCMP(keywords
[i
], "hdc") && (i
+1 < nrofkeywords
)) {
2223 dwFlags
|= MCI_ANIM_UPDATE_HDC
;
2224 sscanf(keywords
[i
+1], "%d", &(updateParams
->hDC
));
2230 updateParams
->dwCallback
= hwndCallback
;
2231 res
= mciSendCommandA(wDevID
, MCI_UPDATE
, dwFlags
, (DWORD
)updateParams
);
2236 /* where command for animation and overlay drivers.
2237 * just returns the specified rectangle as a string
2246 MCISTR_Where(_MCISTR_PROTO_
) {
2248 MCI_ANIM_RECT_PARMS animwhereParams
;
2249 MCI_OVLY_RECT_PARMS ovlywhereParams
;
2251 union U
* pU
= xmalloc(sizeof(union U
));
2254 for (i
= 0; i
< nrofkeywords
; i
++) {
2256 case MCI_DEVTYPE_ANIMATION
:
2257 FLAG1("source", MCI_ANIM_WHERE_SOURCE
);
2258 FLAG1("destination", MCI_ANIM_WHERE_DESTINATION
);
2260 case MCI_DEVTYPE_OVERLAY
:
2261 FLAG1("source", MCI_OVLY_WHERE_SOURCE
);
2262 FLAG1("destination", MCI_OVLY_WHERE_DESTINATION
);
2263 FLAG1("video", MCI_OVLY_WHERE_VIDEO
);
2264 FLAG1("frame", MCI_OVLY_WHERE_FRAME
);
2268 pU
->animwhereParams
.dwCallback
= hwndCallback
;
2269 res
= mciSendCommandA(wDevID
, MCI_WHERE
, dwFlags
, (DWORD
)pU
);
2273 case MCI_DEVTYPE_ANIMATION
:
2274 sprintf(buf
, "%d %d %d %d",
2275 pU
->animwhereParams
.rc
.left
,
2276 pU
->animwhereParams
.rc
.top
,
2277 pU
->animwhereParams
.rc
.right
,
2278 pU
->animwhereParams
.rc
.bottom
2281 case MCI_DEVTYPE_OVERLAY
:
2282 sprintf(buf
, "%d %d %d %d",
2283 pU
->ovlywhereParams
.rc
.left
,
2284 pU
->ovlywhereParams
.rc
.top
,
2285 pU
->ovlywhereParams
.rc
.right
,
2286 pU
->ovlywhereParams
.rc
.bottom
2289 default:strcpy(buf
, "0 0 0 0");break;
2298 MCISTR_Window(_MCISTR_PROTO_
) {
2300 MCI_ANIM_WINDOW_PARMSA animwindowParams
;
2301 MCI_OVLY_WINDOW_PARMSA ovlywindowParams
;
2302 MCI_DGV_WINDOW_PARMSA dgvwindowParams
;
2304 union U
* pU
= xmalloc(sizeof(union U
));
2309 for (i
= 0; i
< nrofkeywords
; ) {
2311 case MCI_DEVTYPE_ANIMATION
:
2312 if (!STRCMP(keywords
[i
], "handle") && (i
+1 < nrofkeywords
)) {
2313 dwFlags
|= MCI_ANIM_WINDOW_HWND
;
2314 if (!STRCMP(keywords
[i
+1], "default"))
2315 pU
->animwindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
2317 sscanf(keywords
[i
+1], "%d", &(pU
->animwindowParams
.hWnd
));
2321 if (!STRCMP(keywords
[i
], "state") && (i
+1 < nrofkeywords
)) {
2322 dwFlags
|= MCI_ANIM_WINDOW_STATE
;
2323 if (!STRCMP(keywords
[i
+1], "hide"))
2324 pU
->animwindowParams
.nCmdShow
= SW_HIDE
;
2325 if (!STRCMP(keywords
[i
+1], "iconic"))
2326 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2327 if (!STRCMP(keywords
[i
+1], "minimized"))
2328 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2329 if (!STRCMP(keywords
[i
+1], "maximized"))
2330 pU
->animwindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2331 if (!STRCMP(keywords
[i
+1], "minimize"))
2332 pU
->animwindowParams
.nCmdShow
= SW_MINIMIZE
;
2333 if (!STRCMP(keywords
[i
+1], "normal"))
2334 pU
->animwindowParams
.nCmdShow
= SW_NORMAL
;
2335 if (!STRCMP(keywords
[i
+1], "restore"))
2336 pU
->animwindowParams
.nCmdShow
= SW_NORMAL
;
2337 if (!STRCMP(keywords
[i
+1], "show"))
2338 pU
->animwindowParams
.nCmdShow
= SW_SHOW
;
2339 if (!STRCMP(keywords
[i
+1], "no") && (i
+2 < nrofkeywords
)) {
2340 if (!STRCMP(keywords
[i
+2], "active"))
2341 pU
->animwindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2342 if (!STRCMP(keywords
[i
+2], "action"))
2343 pU
->animwindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2349 /* text is enclosed in " ... " as it seems */
2350 if (!STRCMP(keywords
[i
], "text")) {
2354 if (keywords
[i
+1][0] != '"') {
2358 dwFlags
|= MCI_ANIM_WINDOW_TEXT
;
2359 len
= strlen(keywords
[i
+1])+1;
2360 for (j
= i
+2; j
< nrofkeywords
; j
++) {
2361 len
+= strlen(keywords
[j
])+1;
2362 if (strchr(keywords
[j
], '"'))
2365 s
= (char*)xmalloc(len
);
2366 strcpy(s
, keywords
[i
+1]+1);
2368 for (j
= i
+ 2; j
<= k
; j
++) {
2370 strcat(s
, keywords
[j
]);
2372 /* FIXME: hhmmm not so sure (strrchr ?) */
2373 if ((t
=strchr(s
, '"'))) *t
='\0';
2374 pU
->animwindowParams
.lpstrText
= s
;
2378 FLAG1("stretch", MCI_ANIM_WINDOW_ENABLE_STRETCH
);
2380 case MCI_DEVTYPE_DIGITAL_VIDEO
:
2381 if (!STRCMP(keywords
[i
], "handle") && (i
+1 < nrofkeywords
)) {
2382 dwFlags
|= MCI_DGV_WINDOW_HWND
;
2383 if (!STRCMP(keywords
[i
+1], "default"))
2384 pU
->dgvwindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
2386 sscanf(keywords
[i
+1], "%d", &(pU
->dgvwindowParams
.hWnd
));
2390 if (!STRCMP(keywords
[i
], "state") && (i
+1 < nrofkeywords
)) {
2391 dwFlags
|= MCI_DGV_WINDOW_STATE
;
2392 if (!STRCMP(keywords
[i
+1], "hide"))
2393 pU
->dgvwindowParams
.nCmdShow
= SW_HIDE
;
2394 if (!STRCMP(keywords
[i
+1], "iconic"))
2395 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2396 if (!STRCMP(keywords
[i
+1], "minimized"))
2397 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2398 if (!STRCMP(keywords
[i
+1], "maximized"))
2399 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2400 if (!STRCMP(keywords
[i
+1], "minimize"))
2401 pU
->dgvwindowParams
.nCmdShow
= SW_MINIMIZE
;
2402 if (!STRCMP(keywords
[i
+1], "normal"))
2403 pU
->dgvwindowParams
.nCmdShow
= SW_NORMAL
;
2404 if (!STRCMP(keywords
[i
+1], "restore"))
2405 pU
->dgvwindowParams
.nCmdShow
= SW_NORMAL
;
2406 if (!STRCMP(keywords
[i
+1], "show"))
2407 pU
->dgvwindowParams
.nCmdShow
= SW_SHOW
;
2408 if (!STRCMP(keywords
[i
+1], "no") && (i
+2 < nrofkeywords
)) {
2409 if (!STRCMP(keywords
[i
+2], "active"))
2410 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2411 if (!STRCMP(keywords
[i
+2], "action"))
2412 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2418 /* text is enclosed in " ... " as it seems */
2419 if (!STRCMP(keywords
[i
], "text")) {
2423 if (keywords
[i
+1][0] != '"') {
2427 dwFlags
|= MCI_DGV_WINDOW_TEXT
;
2428 len
= strlen(keywords
[i
+1])+1;
2429 for (j
= i
+2; j
< nrofkeywords
; j
++) {
2430 len
+= strlen(keywords
[j
])+1;
2431 if (strchr(keywords
[j
], '"'))
2434 s
= (char*)xmalloc(len
);
2435 strcpy(s
, keywords
[i
+1]+1);
2437 for (j
= i
+ 2; j
<= k
; j
++) {
2439 strcat(s
, keywords
[j
]);
2441 /* FIXME: hhmmm not so sure (strrchr ?) */
2442 if ((t
=strchr(s
, '"'))) *t
='\0';
2443 pU
->dgvwindowParams
.lpstrText
= s
;
2449 case MCI_DEVTYPE_OVERLAY
:
2450 if (!STRCMP(keywords
[i
], "handle") && (i
+1 < nrofkeywords
)) {
2451 dwFlags
|= MCI_OVLY_WINDOW_HWND
;
2452 if (!STRCMP(keywords
[i
+1], "default"))
2453 pU
->ovlywindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
2455 sscanf(keywords
[i
+1], "%d", &(pU
->ovlywindowParams
.hWnd
));
2459 if (!STRCMP(keywords
[i
], "state") && (i
+1 < nrofkeywords
)) {
2460 dwFlags
|= MCI_OVLY_WINDOW_STATE
;
2461 if (!STRCMP(keywords
[i
+1], "hide"))
2462 pU
->ovlywindowParams
.nCmdShow
= SW_HIDE
;
2463 if (!STRCMP(keywords
[i
+1], "iconic"))
2464 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2465 if (!STRCMP(keywords
[i
+1], "minimized"))
2466 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2467 if (!STRCMP(keywords
[i
+1], "maximized"))
2468 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2469 if (!STRCMP(keywords
[i
+1], "minimize"))
2470 pU
->ovlywindowParams
.nCmdShow
= SW_MINIMIZE
;
2471 if (!STRCMP(keywords
[i
+1], "normal"))
2472 pU
->ovlywindowParams
.nCmdShow
= SW_NORMAL
;
2473 if (!STRCMP(keywords
[i
+1], "show"))
2474 pU
->ovlywindowParams
.nCmdShow
= SW_SHOW
;
2475 if (!STRCMP(keywords
[i
+1], "no") && (i
+2 < nrofkeywords
)) {
2476 if (!STRCMP(keywords
[i
+2], "active"))
2477 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2478 if (!STRCMP(keywords
[i
+2], "action"))
2479 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2485 /* text is enclosed in " ... " as it seems */
2486 if (!STRCMP(keywords
[i
], "text")) {
2490 if (keywords
[i
+1][0] != '"') {
2494 dwFlags
|= MCI_OVLY_WINDOW_TEXT
;
2495 len
= strlen(keywords
[i
+1])+1;
2496 for (j
= i
+2; j
< nrofkeywords
; j
++) {
2497 len
+= strlen(keywords
[j
])+1;
2498 if (strchr(keywords
[j
], '"'))
2501 s
=(char*)xmalloc(len
);
2502 strcpy(s
, keywords
[i
+1]+1);
2504 for (j
= i
+2; j
<= k
; j
++) {
2506 strcat(s
, keywords
[j
]);
2508 if ((t
=strchr(s
, '"'))) *t
='\0';
2509 pU
->ovlywindowParams
.lpstrText
= s
;
2513 FLAG1("stretch", MCI_OVLY_WINDOW_ENABLE_STRETCH
);
2518 pU
->animwindowParams
.dwCallback
= hwndCallback
;
2519 res
= mciSendCommandA(wDevID
, MCI_WINDOW
, dwFlags
, (DWORD
)pU
);
2525 struct _MCISTR_cmdtable
{
2527 DWORD (*fun
)(_MCISTR_PROTO_
);
2528 } MCISTR_cmdtable
[]={
2529 {"break", MCISTR_Break
},
2530 {"capability", MCISTR_Capability
},
2531 {"close", MCISTR_Close
},
2532 {"cue", MCISTR_Cue
},
2533 {"delete", MCISTR_Delete
},
2534 {"escape", MCISTR_Escape
},
2535 {"freeze", MCISTR_Freeze
},
2536 {"info", MCISTR_Info
},
2537 {"load", MCISTR_Load
},
2538 {"open", MCISTR_Open
},
2539 {"pause", MCISTR_Pause
},
2540 {"play", MCISTR_Play
},
2541 {"put", MCISTR_Put
},
2542 {"realize", MCISTR_Realize
},
2543 {"record", MCISTR_Record
},
2544 {"resume", MCISTR_Resume
},
2545 {"save", MCISTR_Save
},
2546 {"seek", MCISTR_Seek
},
2547 {"set", MCISTR_Set
},
2548 {"setaudio", MCISTR_SetAudio
},
2549 {"spin", MCISTR_Spin
},
2550 {"status", MCISTR_Status
},
2551 {"step", MCISTR_Step
},
2552 {"stop", MCISTR_Stop
},
2553 {"sysinfo", MCISTR_Sysinfo
},
2554 {"unfreeze", MCISTR_Unfreeze
},
2555 {"update", MCISTR_Update
},
2556 {"where", MCISTR_Where
},
2557 {"window", MCISTR_Window
},
2561 /**************************************************************************
2562 * mciSendString16 [MMSYSTEM.702]
2564 /* The usercode sends a string with a command (and flags) expressed in
2565 * words in it... We do our best to call appropriate drivers,
2566 * and return a errorcode AND a readable string (if lpstrRS != NULL)
2567 * Info gathered by watching cool134.exe and from Borland's mcistrwh.hlp
2569 /* FIXME: "all" is a valid devicetype and we should access all devices if
2570 * it is used. (imagine "close all"). Not implemented yet.
2572 DWORD WINAPI
mciSendString16(LPCSTR lpstrCommand
, LPSTR lpstrReturnString
,
2573 UINT16 uReturnLength
, HWND16 hwndCallback
)
2575 char *cmd
, *dev
, *args
, **keywords
;
2576 WORD uDevTyp
= 0, wDevID
= 0;
2578 int res
= 0, i
, nrofkeywords
;
2580 TRACE(mci
, "('%s', %p, %d, %X)\n",
2581 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2583 /* format is <command> <device> <optargs> */
2584 cmd
= strdup(lpstrCommand
);
2585 dev
= strchr(cmd
, ' ');
2588 return MCIERR_MISSING_DEVICE_NAME
;
2591 args
= strchr(dev
, ' ');
2592 if (args
!= NULL
) *args
++ = '\0';
2596 i
= 1;/* nrofkeywords = nrofspaces+1 */
2598 while ((s
= strchr(s
, ' ')) != NULL
) i
++, s
++;
2599 keywords
= (char**)xmalloc(sizeof(char*) * (i
+ 2));
2602 while (s
&& i
< nrofkeywords
) {
2610 keywords
= (char**)xmalloc(sizeof(char*));
2612 dwFlags
= 0; /* default flags */
2613 for (i
= 0; i
< nrofkeywords
;) {
2614 if (!STRCMP(keywords
[i
], "wait")) {
2615 dwFlags
|= MCI_WAIT
;
2616 memcpy(keywords
+i
, keywords
+(i
+1), (nrofkeywords
-i
-1) * sizeof(char*));
2620 if (!STRCMP(keywords
[i
], "notify")) {
2621 dwFlags
|= MCI_NOTIFY
;
2622 memcpy(keywords
+i
, keywords
+(i
+1), (nrofkeywords
-i
-1) * sizeof(char*));
2629 /* determine wDevID and uDevTyp for all commands except "open" */
2630 if (STRCMP(cmd
, "open") != 0) {
2631 wDevID
= mciGetDeviceIDA(dev
);
2633 TRACE(mci
, "Device '%s' not found!\n", dev
);
2634 res
= MCIERR_INVALID_DEVICE_NAME
;
2637 uDevTyp
= MCI_GetDrv(wDevID
)->modp
.wType
;
2640 for (i
= 0; MCISTR_cmdtable
[i
].cmd
!= NULL
; i
++) {
2641 if (!STRCMP(MCISTR_cmdtable
[i
].cmd
, cmd
)) {
2642 res
= MCISTR_cmdtable
[i
].fun(wDevID
, uDevTyp
, lpstrReturnString
,
2643 uReturnLength
, dev
, (LPSTR
*)keywords
,
2644 nrofkeywords
, dwFlags
, hwndCallback
);
2648 if (MCISTR_cmdtable
[i
].cmd
== NULL
) {
2649 FIXME(mci
, "('%s', %p, %u, %X): unimplemented, please report.\n",
2650 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2651 res
= MCIERR_MISSING_COMMAND_STRING
;
2654 free(keywords
); free(cmd
);
2658 /**************************************************************************
2659 * mciSendStringA [MMSYSTEM.702][WINMM.51]
2661 DWORD WINAPI
mciSendStringA(LPCSTR lpstrCommand
, LPSTR lpstrReturnString
,
2662 UINT uReturnLength
, HWND hwndCallback
)
2664 return mciSendString16(lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2667 /**************************************************************************
2668 * mciSendStringW [WINMM.52]
2670 DWORD WINAPI
mciSendStringW(LPCWSTR lpwstrCommand
, LPSTR lpstrReturnString
,
2671 UINT uReturnLength
, HWND hwndCallback
)
2676 /* FIXME: is there something to do with lpstrReturnString ? */
2677 lpstrCommand
= HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrCommand
);
2678 ret
= mciSendString16(lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2679 HeapFree(GetProcessHeap(), 0, lpstrCommand
);
2683 /**************************************************************************
2684 * mciExecute [WINMM.38]
2686 DWORD WINAPI
mciExecute(LPCSTR lpstrCommand
)
2691 TRACE(mci
, "(%s)!\n", lpstrCommand
);
2693 ret
= mciSendString16(lpstrCommand
, strRet
, sizeof(strRet
), 0);
2695 if (!mciGetErrorString16(ret
, strRet
, sizeof(strRet
))) {
2696 sprintf(strRet
, "Unknown MCI error (%ld)", ret
);
2698 MessageBoxA(0, strRet
, "Error in mciExecute()", MB_OK
);
2700 /* FIXME: what shall I return ? */