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 "multimedia.h"
25 #include "debugtools.h"
28 DEFAULT_DEBUG_CHANNEL(mci
)
30 /* The reason why I just don't lowercase the keywords array in
31 * mciSendString is left as an exercise to the reader.
32 * (EP: For the blinds, like me, it's linked to file name handling
33 * which is case sensitive).
35 #define STRCMP(x, y) lstrcmpiA(x, y)
37 /* standard function parameters for all functions */
38 #define _MCISTR_PROTO_ \
39 WORD wDevID, WORD uDevTyp, LPSTR lpstrReturnString, \
40 UINT16 uReturnLength, LPCSTR dev, LPSTR* keywords, \
41 UINT16 nrofkeywords, DWORD dwFlags, HWND16 hwndCallback
43 /* copy string to return pointer including necessary checks
44 * for use in mciSendString()
48 TRACE("-> returns '%s'\n", s); \
49 if (lpstrReturnString) { \
50 lstrcpynA(lpstrReturnString, s, uReturnLength); \
51 TRACE("--> '%s'\n", lpstrReturnString); \
55 static LPSTR
_MCISTR_Unquote(LPSTR str
)
58 int i
, len
= strlen(str
);
60 if (len
> 1 && str
[0] == '"' && str
[len
-1] == '"') {
61 for (i
= 1; i
< len
-1; i
++) {
70 /* print a DWORD in the specified timeformat */
72 _MCISTR_printtf(char *buf
, UINT16 uDevType
, DWORD timef
, DWORD val
)
76 case MCI_FORMAT_MILLISECONDS
:
77 case MCI_FORMAT_FRAMES
:
78 case MCI_FORMAT_BYTES
:
79 case MCI_FORMAT_SAMPLES
:
80 case MCI_VD_FORMAT_TRACK
:
81 /*case MCI_SEQ_FORMAT_SONGPTR: sameas MCI_VD_FORMAT_TRACK */
82 sprintf(buf
, "%ld", val
);
85 /* well, the macros have the same content*/
88 sprintf(buf
, "%d:%d:%d",
94 sprintf(buf
, "%d:%d:%d:%d",
101 FIXME("missing timeformat for %ld, report.\n", timef
);
102 strcpy(buf
, "0"); /* hmm */
107 /* possible different return types */
108 #define _MCISTR_int 1
109 #define _MCISTR_time 2
110 #define _MCISTR_bool 3
111 #define _MCISTR_tfname 4
112 #define _MCISTR_mode 5
113 #define _MCISTR_divtype 6
114 #define _MCISTR_seqtype 7
115 #define _MCISTR_vdmtype 8
116 #define _MCISTR_devtype 9
119 _MCISTR_convreturn(int type
, DWORD dwReturn
, LPSTR lpstrReturnString
,
120 WORD uReturnLength
, WORD uDevTyp
, int timef
)
123 case _MCISTR_vdmtype
:
125 case MCI_VD_MEDIA_CLV
: _MCI_STR("CLV"); break;
126 case MCI_VD_MEDIA_CAV
: _MCI_STR("CAV"); break;
128 case MCI_VD_MEDIA_OTHER
:_MCI_STR("other"); break;
131 case _MCISTR_seqtype
:
133 case MCI_SEQ_NONE
: _MCI_STR("none"); break;
134 case MCI_SEQ_SMPTE
: _MCI_STR("smpte"); break;
135 case MCI_SEQ_FILE
: _MCI_STR("file"); break;
136 case MCI_SEQ_MIDI
: _MCI_STR("midi"); break;
137 default:FIXME("missing sequencer mode %ld\n", dwReturn
);
142 case MCI_MODE_NOT_READY
:_MCI_STR("not ready"); break;
143 case MCI_MODE_STOP
: _MCI_STR("stopped"); break;
144 case MCI_MODE_PLAY
: _MCI_STR("playing"); break;
145 case MCI_MODE_RECORD
: _MCI_STR("recording"); break;
146 case MCI_MODE_SEEK
: _MCI_STR("seeking"); break;
147 case MCI_MODE_PAUSE
: _MCI_STR("paused"); break;
148 case MCI_MODE_OPEN
: _MCI_STR("open"); break;
160 sprintf(buf
, "%ld", dwReturn
);
166 _MCISTR_printtf(buf
, uDevTyp
, timef
, dwReturn
);
172 case MCI_FORMAT_MILLISECONDS
: _MCI_STR("milliseconds"); break;
173 case MCI_FORMAT_FRAMES
: _MCI_STR("frames"); break;
174 case MCI_FORMAT_BYTES
: _MCI_STR("bytes"); break;
175 case MCI_FORMAT_SAMPLES
: _MCI_STR("samples"); break;
176 case MCI_FORMAT_HMS
: _MCI_STR("hms"); break;
177 case MCI_FORMAT_MSF
: _MCI_STR("msf"); break;
178 case MCI_FORMAT_TMSF
: _MCI_STR("tmsf"); break;
180 FIXME("missing timefmt for %d, report.\n", timef
);
184 case _MCISTR_divtype
:
186 case MCI_SEQ_DIV_PPQN
: _MCI_STR("PPQN"); break;
187 case MCI_SEQ_DIV_SMPTE_24
: _MCI_STR("SMPTE 24 frame"); break;
188 case MCI_SEQ_DIV_SMPTE_25
: _MCI_STR("SMPTE 25 frame"); break;
189 case MCI_SEQ_DIV_SMPTE_30
: _MCI_STR("SMPTE 30 frame"); break;
190 case MCI_SEQ_DIV_SMPTE_30DROP
: _MCI_STR("SMPTE 30 frame drop");break;
192 case _MCISTR_devtype
:
194 case MCI_DEVTYPE_VCR
: _MCI_STR("vcr"); break;
195 case MCI_DEVTYPE_VIDEODISC
: _MCI_STR("videodisc"); break;
196 case MCI_DEVTYPE_CD_AUDIO
: _MCI_STR("cd audio"); break;
197 case MCI_DEVTYPE_OVERLAY
: _MCI_STR("overlay"); break;
198 case MCI_DEVTYPE_DAT
: _MCI_STR("dat"); break;
199 case MCI_DEVTYPE_SCANNER
: _MCI_STR("scanner"); break;
200 case MCI_DEVTYPE_ANIMATION
: _MCI_STR("animation"); break;
201 case MCI_DEVTYPE_DIGITAL_VIDEO
: _MCI_STR("digital video"); break;
202 case MCI_DEVTYPE_OTHER
: _MCI_STR("other"); break;
203 case MCI_DEVTYPE_WAVEFORM_AUDIO
:_MCI_STR("waveform audio"); break;
204 case MCI_DEVTYPE_SEQUENCER
: _MCI_STR("sequencer"); break;
205 default:FIXME("unknown device type %ld, report.\n",
210 FIXME("unknown resulttype %d, report.\n", type
);
215 #define FLAG1(str, flag) \
216 if (!STRCMP(keywords[i], str)) { \
222 #define FLAG2(str1, str2, flag) \
223 if (!STRCMP(keywords[i], str1) && \
224 (i+1 < nrofkeywords) && \
225 !STRCMP(keywords[i+1], str2)) { \
231 /* All known subcommands are implemented in single functions to avoid
232 * bloat and a xxxx lines long mciSendString(). All commands are of the
233 * format MCISTR_Cmd(_MCISTR_PROTO_) where _MCISTR_PROTO_ is the above
234 * defined line of arguments. (This is just for easy enhanceability.)
235 * All functions return the MCIERR_ errorvalue as DWORD. Returnvalues
236 * for the calls are in lpstrReturnString (If I mention return values
237 * in function headers, I mean returnvalues in lpstrReturnString.)
238 * Integers are sprintf("%d")ed integers. Boolean values are
239 * "true" and "false".
240 * timeformat depending values are "%d" "%d:%d" "%d:%d:%d" "%d:%d:%d:%d"
241 * FIXME: is above line correct?
243 * Preceding every function is a list of implemented/known arguments.
244 * Feel free to add missing arguments.
249 * Opens the specified MCI driver.
253 * "alias <aliasname>"
254 * "element <elementname>"
257 * "buffer <nrBytesPerSec>"
259 * "nostatic" increaste nr of nonstatic colours
260 * "parent <windowhandle>"
261 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
262 * "style child" WS_CHILD
263 * "style overlap" WS_OVERLAPPED
264 * "style popup" WS_POPUP
266 * "parent <windowhandle>"
267 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
268 * "style child" WS_CHILD
269 * "style overlap" WS_OVERLAPPED
270 * "style popup" WS_POPUP
274 MCISTR_Open(_MCISTR_PROTO_
)
279 MCI_OPEN_PARMSA openParams
;
280 MCI_WAVE_OPEN_PARMSA waveopenParams
;
281 MCI_ANIM_OPEN_PARMSA animopenParams
;
282 MCI_OVLY_OPEN_PARMSA ovlyopenParams
;
283 MCI_DGV_OPEN_PARMSA dgvopenParams
;
285 union U
* pU
= xmalloc(sizeof(union U
));
287 pU
->openParams
.lpstrElementName
= NULL
;
288 s
= strchr(dev
, '!');
291 pU
->openParams
.lpstrElementName
= strdup(s
);
292 dwFlags
|= MCI_OPEN_ELEMENT
;
294 for (i
= 0; i
< nrofkeywords
; ) {
295 if ((!STRCMP(keywords
[i
], "type")) && (i
< nrofkeywords
-1)) {
296 pU
->openParams
.lpstrElementName
= strdup(dev
);
297 dwFlags
|= MCI_OPEN_ELEMENT
;
299 /* FIXME: isn't there a memory leak here ? keyword+i ? */
300 memcpy(keywords
+i
, keywords
+(i
+2), (nrofkeywords
-i
-2) * sizeof(char*));
307 CharUpperA((char*)dev
);
308 uDevTyp
= MCI_GetDevTypeFromString(dev
);
310 free(pU
->openParams
.lpstrElementName
);
312 return MCIERR_INVALID_DEVICE_NAME
;
315 pU
->openParams
.dwCallback
= hwndCallback
;
316 pU
->openParams
.wDeviceID
= wDevID
;
317 pU
->ovlyopenParams
.dwStyle
= 0;
318 pU
->animopenParams
.dwStyle
= 0;
319 pU
->openParams
.lpstrDeviceType
= strdup(dev
);
320 pU
->openParams
.lpstrAlias
= NULL
;
321 dwFlags
|= MCI_OPEN_TYPE
;
322 for (i
= 0; i
< nrofkeywords
; ) {
323 FLAG1("shareable", MCI_OPEN_SHAREABLE
);
324 if (!STRCMP(keywords
[i
], "alias") && (i
+1 < nrofkeywords
)) {
325 dwFlags
|= MCI_OPEN_ALIAS
;
326 pU
->openParams
.lpstrAlias
= strdup(keywords
[i
+1]);
330 if (!STRCMP(keywords
[i
], "element") && (i
+1 < nrofkeywords
)) {
331 dwFlags
|= MCI_OPEN_ELEMENT
;
332 assert(pU
->openParams
.lpstrElementName
== NULL
);
333 pU
->openParams
.lpstrElementName
= strdup(keywords
[i
+1]);
338 case MCI_DEVTYPE_ANIMATION
:
339 FLAG1("nostatic", MCI_ANIM_OPEN_NOSTATIC
);
340 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
341 dwFlags
|= MCI_ANIM_OPEN_PARENT
;
342 sscanf(keywords
[i
+1], "%u", &(pU
->animopenParams
.hWndParent
));
346 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
349 dwFlags
|= MCI_ANIM_OPEN_WS
;
350 if (!STRCMP(keywords
[i
+1], "popup")) {
351 pU
->animopenParams
.dwStyle
|= WS_POPUP
;
352 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
353 pU
->animopenParams
.dwStyle
|= WS_OVERLAPPED
;
354 } else if (!STRCMP(keywords
[i
+1], "child")) {
355 pU
->animopenParams
.dwStyle
|= WS_CHILD
;
356 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
357 pU
->animopenParams
.dwStyle
|= st
;
359 FIXME("unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
364 case MCI_DEVTYPE_DIGITAL_VIDEO
:
365 FLAG1("nostatic", MCI_ANIM_OPEN_NOSTATIC
);
366 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
367 dwFlags
|= MCI_DGV_OPEN_PARENT
;
368 sscanf(keywords
[i
+1], "%u", &(pU
->dgvopenParams
.hWndParent
));
372 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
375 dwFlags
|= MCI_DGV_OPEN_WS
;
376 if (!STRCMP(keywords
[i
+1], "popup")) {
377 pU
->dgvopenParams
.dwStyle
|= WS_POPUP
;
378 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
379 pU
->dgvopenParams
.dwStyle
|= WS_OVERLAPPED
;
380 } else if (!STRCMP(keywords
[i
+1], "child")) {
381 pU
->dgvopenParams
.dwStyle
|= WS_CHILD
;
382 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
383 pU
->dgvopenParams
.dwStyle
|= st
;
385 FIXME("unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
390 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
391 if (!STRCMP(keywords
[i
], "buffer") && (i
+1 < nrofkeywords
)) {
392 dwFlags
|= MCI_WAVE_OPEN_BUFFER
;
393 sscanf(keywords
[i
+1], "%ld", &(pU
->waveopenParams
.dwBufferSeconds
));
396 case MCI_DEVTYPE_OVERLAY
:
397 /* looks just like anim, but without NOSTATIC */
398 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
399 dwFlags
|= MCI_OVLY_OPEN_PARENT
;
400 sscanf(keywords
[i
+1], "%u", &(pU
->ovlyopenParams
.hWndParent
));
404 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
407 dwFlags
|= MCI_OVLY_OPEN_WS
;
408 if (!STRCMP(keywords
[i
+1], "popup")) {
409 pU
->ovlyopenParams
.dwStyle
|= WS_POPUP
;
410 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
411 pU
->ovlyopenParams
.dwStyle
|= WS_OVERLAPPED
;
412 } else if (!STRCMP(keywords
[i
+1], "child")) {
413 pU
->ovlyopenParams
.dwStyle
|= WS_CHILD
;
414 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
415 pU
->ovlyopenParams
.dwStyle
|= st
;
417 FIXME("unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
423 FIXME("unknown parameter passed %s, please report.\n",
428 _MCISTR_Unquote(pU
->openParams
.lpstrElementName
);
430 res
= mciSendCommandA(0, MCI_OPEN
, dwFlags
, (DWORD
)pU
);
433 snprintf(lpstrReturnString
, uReturnLength
, "%d", pU
->openParams
.wDeviceID
);
436 free(pU
->openParams
.lpstrElementName
);
437 free(pU
->openParams
.lpstrDeviceType
);
438 free(pU
->openParams
.lpstrAlias
);
443 /* A helper function for a lot of others ...
444 * for instance status/play/record/seek etc.
447 _MCISTR_determine_timeformat(LPCSTR dev
, WORD wDevID
, WORD uDevTyp
, int *timef
)
450 DWORD dwFlags
= MCI_STATUS_ITEM
;
451 LPMCI_STATUS_PARMS statusParams
= xmalloc(sizeof(MCI_STATUS_PARMS
));
453 if (!statusParams
) return 0;
454 statusParams
->dwItem
= MCI_STATUS_TIME_FORMAT
;
455 statusParams
->dwReturn
= 0;
456 res
= mciSendCommandA(wDevID
, MCI_STATUS
, dwFlags
, (DWORD
)statusParams
);
458 if (res
== 0) *timef
= statusParams
->dwReturn
;
463 /* query status of MCI drivers
466 * "mode" - returns "not ready" "paused" "playing" "stopped" "open"
467 * "parked" "recording" "seeking" ....
469 * "current track" - returns current track as integer
470 * "length [track <nr>]" - returns length [of track <nr>] in current
472 * "number of tracks" - returns number of tracks as integer
473 * "position [track <nr>]" - returns position [in track <nr>] in current
475 * "ready" - checks if device is ready to play, -> bool
476 * "start position" - returns start position in timeformat
477 * "time format" - returns timeformat (list of possible values:
478 * "ms" "msf" "milliseconds" "hmsf" "tmsf" "frames"
479 * "bytes" "samples" "hms")
480 * "media present" - returns if media is present as bool
482 * "forward" - returns "true" if device is playing forwards
483 * "speed" - returns speed for device
484 * "palette handle" - returns palette handle
485 * "window handle" - returns window handle
486 * "stretch" - returns stretch bool
488 * "division type" - ? returns "PPQN" "SMPTE 24 frame"
489 * "SMPTE 25 frame" "SMPTE 30 frame" "SMPTE 30 drop frame"
490 * "tempo" - current tempo in (PPQN? speed in frames, SMPTE*? speed in hsmf)
491 * "offset" - offset in dito.
492 * "port" - midi port as integer
493 * "slave" - slave device ("midi", "file", "none", "smpte")
494 * "master" - masterdevice (dito.)
496 * "window handle" - see animation
499 * "speed" - speed as integer
500 * "forward" - returns bool (when playing forward)
501 * "side" - returns 1 or 2
502 * "media type" - returns "CAV" "CLV" "other"
503 * "disc size" - returns "8" or "12"
505 * "input" - base queries on input set
506 * "output" - base queries on output set
507 * "format tag" - return integer format tag
508 * "channels" - return integer nr of channels
509 * "bytespersec" - return average nr of bytes/sec
510 * "samplespersec" - return nr of samples per sec
511 * "bitspersample" - return bitspersample
512 * "alignment" - return block alignment
513 * "level" - return level?
517 * "audio bitspersample"
519 * "audio bytespersec"
523 * "audio samplespersec"
544 * "nominal frame rate"
545 * "nominal record frame rate"
550 * "record frame rate"
558 * "still file format"
567 * "video source number"
576 #define ITEM1(str, item, xtype) \
577 if (!STRCMP(keywords[i], str)) { \
578 pU->statusParams.dwItem = item; \
583 #define ITEM2(str1, str2, item, xtype) \
584 if ( !STRCMP(keywords[i], str1) && \
585 (i+1 < nrofkeywords) && \
586 !STRCMP(keywords[i+1], str2)) { \
587 pU->statusParams.dwItem = item; \
592 #define ITEM3(str1, str2, str3, item, xtype) \
593 if ( !STRCMP(keywords[i], str1) && \
594 (i+2 < nrofkeywords) && \
595 !STRCMP(keywords[i+1], str2) && \
596 !STRCMP(keywords[i+2], str3)) { \
597 pU->statusParams.dwItem = item; \
602 #define ITEM4(str1, str2, str3, str4, item, xtype) \
603 if ( !STRCMP(keywords[i], str1) && \
604 (i+3 < nrofkeywords) && \
605 !STRCMP(keywords[i+1], str2) && \
606 !STRCMP(keywords[i+2], str3) && \
607 !STRCMP(keywords[i+3], str4)) { \
608 pU->statusParams.dwItem = item; \
615 MCISTR_Status(_MCISTR_PROTO_
) {
617 MCI_STATUS_PARMS statusParams
;
618 MCI_DGV_STATUS_PARMSA dgvstatusParams
;
620 union U
* pU
= xmalloc(sizeof(union U
));
621 int type
= 0, i
, res
, timef
;
623 pU
->statusParams
.dwCallback
= hwndCallback
;
624 dwFlags
|= MCI_STATUS_ITEM
;
625 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
628 pU
->statusParams
.dwReturn
= 0;
629 pU
->statusParams
.dwItem
= 0;
631 for (i
= 0; i
< nrofkeywords
; ) {
632 if (!STRCMP(keywords
[i
], "track") && (i
+1 < nrofkeywords
)) {
633 sscanf(keywords
[i
+1], "%ld", &(pU
->statusParams
.dwTrack
));
634 dwFlags
|= MCI_TRACK
;
638 FLAG1("start", MCI_STATUS_START
);
640 ITEM2("current", "track", MCI_STATUS_CURRENT_TRACK
, _MCISTR_time
);
641 ITEM2("time", "format", MCI_STATUS_TIME_FORMAT
, _MCISTR_tfname
);
642 ITEM1("ready", MCI_STATUS_READY
, _MCISTR_bool
);
643 ITEM1("mode", MCI_STATUS_MODE
, _MCISTR_mode
);
644 ITEM3("number", "of", "tracks", MCI_STATUS_NUMBER_OF_TRACKS
, _MCISTR_int
);
645 ITEM1("length", MCI_STATUS_LENGTH
, _MCISTR_time
);
646 ITEM1("position", MCI_STATUS_POSITION
, _MCISTR_time
);
647 ITEM2("media", "present", MCI_STATUS_MEDIA_PRESENT
, _MCISTR_bool
);
650 case MCI_DEVTYPE_ANIMATION
:
651 ITEM2("palette", "handle", MCI_ANIM_STATUS_HPAL
, _MCISTR_int
);
652 ITEM2("window", "handle", MCI_ANIM_STATUS_HWND
, _MCISTR_int
);
653 ITEM1("stretch", MCI_ANIM_STATUS_STRETCH
, _MCISTR_bool
);
654 ITEM1("speed", MCI_ANIM_STATUS_SPEED
, _MCISTR_int
);
655 ITEM1("forward", MCI_ANIM_STATUS_FORWARD
, _MCISTR_bool
);
657 case MCI_DEVTYPE_SEQUENCER
:
658 /* just completing the list, not working correctly */
659 ITEM2("division", "type", MCI_SEQ_STATUS_DIVTYPE
, _MCISTR_divtype
);
660 /* tempo ... PPQN in frames/second, SMPTE in hmsf */
661 ITEM1("tempo", MCI_SEQ_STATUS_TEMPO
, _MCISTR_int
);
662 ITEM1("port", MCI_SEQ_STATUS_PORT
, _MCISTR_int
);
663 ITEM1("slave", MCI_SEQ_STATUS_SLAVE
, _MCISTR_seqtype
);
664 ITEM1("master", MCI_SEQ_STATUS_SLAVE
, _MCISTR_seqtype
);
665 /* offset ... PPQN in frames/second, SMPTE in hmsf */
666 ITEM1("offset", MCI_SEQ_STATUS_SLAVE
, _MCISTR_time
);
668 case MCI_DEVTYPE_OVERLAY
:
669 ITEM2("window", "handle", MCI_OVLY_STATUS_HWND
, _MCISTR_int
);
670 ITEM1("stretch", MCI_OVLY_STATUS_STRETCH
, _MCISTR_bool
);
672 case MCI_DEVTYPE_VIDEODISC
:
673 ITEM1("speed", MCI_VD_STATUS_SPEED
, _MCISTR_int
);
674 ITEM1("forward", MCI_VD_STATUS_FORWARD
, _MCISTR_bool
);
675 ITEM1("side", MCI_VD_STATUS_SIDE
, _MCISTR_int
);
676 ITEM2("media", "type", MCI_VD_STATUS_SIDE
, _MCISTR_vdmtype
);
677 /* returns 8 or 12 */
678 ITEM2("disc", "size", MCI_VD_STATUS_DISC_SIZE
, _MCISTR_int
);
680 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
681 /* I am not quite sure if foll. 2 lines are right. */
682 FLAG1("input", MCI_WAVE_INPUT
);
683 FLAG1("output", MCI_WAVE_OUTPUT
);
685 ITEM2("format", "tag", MCI_WAVE_STATUS_FORMATTAG
, _MCISTR_int
);
686 ITEM1("channels", MCI_WAVE_STATUS_CHANNELS
, _MCISTR_int
);
687 ITEM1("bytespersec", MCI_WAVE_STATUS_AVGBYTESPERSEC
, _MCISTR_int
);
688 ITEM1("samplespersec", MCI_WAVE_STATUS_SAMPLESPERSEC
, _MCISTR_int
);
689 ITEM1("bitspersample", MCI_WAVE_STATUS_BITSPERSAMPLE
, _MCISTR_int
);
690 ITEM1("alignment", MCI_WAVE_STATUS_BLOCKALIGN
, _MCISTR_int
);
691 ITEM1("level", MCI_WAVE_STATUS_LEVEL
, _MCISTR_int
);
693 case MCI_DEVTYPE_DIGITAL_VIDEO
:
694 ITEM1("audio", MCI_DGV_STATUS_AUDIO
, _MCISTR_bool
); /* FIXME? doc says MCI_ON/MCI_OFF */
695 ITEM2("audio", "alignment", MCI_DGV_STATUS_BLOCKALIGN
, _MCISTR_int
);
696 ITEM2("audio", "bitspersample", MCI_DGV_STATUS_BITSPERSAMPLE
, _MCISTR_int
);
697 /* EPP ITEM2("audio", "breaks", MCI_AVI_STATUS_AUDIO_BREAKS, _MCISTR_int); */
698 ITEM2("audio", "bytespersec", MCI_DGV_STATUS_AVGBYTESPERSEC
, _MCISTR_int
);
699 ITEM2("audio", "input", MCI_DGV_STATUS_AUDIO_INPUT
, _MCISTR_int
);
700 ITEM2("audio", "record", MCI_DGV_STATUS_AUDIO_RECORD
, _MCISTR_bool
); /* FIXME? doc says MCI_ON/MCI_OFF */
701 ITEM3("audio", "source", "number", MCI_DGV_STATUS_AUDIO_SOURCE
, _MCISTR_int
);
702 /* FIXME: ITEM2("audio", "source", MCI_DGV_STATUS_AUDIO_SOURCE, _MCISTR_dgvaudiosource); */
703 /* EPP ITEM2("audio", "samplespersec", MCI_DGV_STATUS_SAMPLESPERSECOND, _MCISTR_int); */
704 ITEM2("audio", "stream", MCI_DGV_STATUS_AUDIO_STREAM
, _MCISTR_int
);
705 ITEM1("bass", MCI_DGV_STATUS_BASS
, _MCISTR_int
);
706 ITEM1("bitsperpel", MCI_DGV_STATUS_BITSPERPEL
, _MCISTR_int
);
707 ITEM1("brightness", MCI_DGV_STATUS_BRIGHTNESS
, _MCISTR_int
);
708 ITEM1("color", MCI_DGV_STATUS_COLOR
, _MCISTR_int
);
709 ITEM1("contrast", MCI_DGV_STATUS_CONTRAST
, _MCISTR_int
);
710 /* EPP * "disk space drive" FIXME */
711 ITEM2("file", "completion", MCI_DGV_STATUS_FILE_COMPLETION
, _MCISTR_int
);
712 /* EPP ITEM2("file", "format", MCI_DGV_STATUS_FILEFORMAT, _MCISTR_???); */
713 /* EPP ITEM2("file", "mode", MCI_DGV_STATUS_FILE_MODE, _MCISTR_gdvfileformat); */
714 ITEM1("forward", MCI_DGV_STATUS_FORWARD
, _MCISTR_bool
);
715 /* EPP ITEM2("frames", "skipped", MCI_AVI_STATUS_FRAMES_SKIPPED, _MCISTR_int); */
716 ITEM1("gamma", MCI_DGV_STATUS_GAMMA
, _MCISTR_int
);
717 ITEM2("input", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
718 ITEM2("input", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
719 ITEM2("input", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
720 ITEM2("input", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
721 ITEM2("input", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
722 ITEM2("input", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
723 ITEM2("input", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
724 ITEM2("input", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
726 ITEM2("left", "volume", MCI_DGV_STATUS_VOLUME
|MCI_DGV_STATUS_LEFT
, _MCISTR_int
);
727 ITEM2("media", "present", MCI_STATUS_MEDIA_PRESENT
, _MCISTR_bool
);
728 /* EPP ITEM2("monitor", "method", MCI_DGV_STATUS_MONITOR_METHOD, _MCISTR_monitor); */
729 /* EPP ITEM1("monitor", MCI_DGV_STATUS_MONITOR, _MCISTR_monitor2); */
730 ITEM2("nominal", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
731 ITEM2("nominal", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
732 ITEM2("nominal", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
733 ITEM2("nominal", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
734 ITEM2("nominal", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
735 ITEM2("nominal", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
736 ITEM2("nominal", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
737 ITEM2("nominal", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
738 ITEM3("nominal", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
739 ITEM4("nominal", "record", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_RECORD
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
740 ITEM2("output", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
741 ITEM2("output", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
742 ITEM2("output", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
743 ITEM2("output", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
744 ITEM2("output", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
745 ITEM2("output", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
746 ITEM2("output", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
747 ITEM2("output", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
748 ITEM2("palette", "handle", MCI_DGV_STATUS_HPAL
, _MCISTR_int
); /* FIXME? */
749 ITEM2("pause", "mode", MCI_DGV_STATUS_PAUSE_MODE
, _MCISTR_bool
); /* FIXME */
750 /* EPP ITEM2("play", "speed", MCI_AVI_STATUS_LAST_PLAY_SPEED, _MCISTR_int); */
751 ITEM3("record", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_RECORD
, _MCISTR_int
);
752 ITEM2("reference", "frame", MCI_DGV_STATUS_FRAME_RATE
, _MCISTR_int
); /* FIXME */
753 ITEM2("reserved", "size", MCI_DGV_STATUS_SIZE
, _MCISTR_int
);
754 ITEM2("right", "volume", MCI_DGV_STATUS_VOLUME
|MCI_DGV_STATUS_RIGHT
, _MCISTR_int
);
755 ITEM2("seek", "exactly", MCI_DGV_STATUS_SEEK_EXACTLY
, _MCISTR_bool
);
756 ITEM1("sharpness", MCI_DGV_STATUS_SHARPNESS
, _MCISTR_int
);
757 /* EPP ITEM1("smpte", MCI_DGV_STATUS_SMPTE, _MCISTR_smpte); */
758 /* EPP ITEM1("speed", MCI_DGV_STATUS_SPEED, _MCISTR_speed); */
759 /* EPP ITEM3("still", "file", "format", MCI_DGV_STATUS_STILL_FILEFORMAT, _MCISTR_???); */
760 ITEM1("tint", MCI_DGV_STATUS_TINT
, _MCISTR_int
);
761 ITEM1("treble", MCI_DGV_STATUS_TREBLE
, _MCISTR_int
);
762 ITEM1("unsaved", MCI_DGV_STATUS_UNSAVED
, _MCISTR_bool
);
763 ITEM3("video", "key", "index", MCI_DGV_STATUS_KEY_INDEX
, _MCISTR_int
);
764 ITEM3("video", "key", "color", MCI_DGV_STATUS_KEY_COLOR
, _MCISTR_bool
);
765 ITEM2("video", "record", MCI_DGV_STATUS_VIDEO_RECORD
, _MCISTR_bool
); /* FIXME MCI_ON/OFF */
766 ITEM3("video", "source", "number", MCI_DGV_STATUS_VIDEO_SOURCE
, _MCISTR_int
);
767 /* EPP ITEM2("video", "source", MCI_DGV_STATUS_VIDEO_SOURCE, _MCISTR_videosrctype); */
768 ITEM2("video", "stream", MCI_DGV_STATUS_VIDEO_STREAM
, _MCISTR_int
);
769 ITEM1("video", MCI_DGV_STATUS_VIDEO
, _MCISTR_bool
); /* FIXME MCI_ON/OFF */
770 ITEM1("volume", MCI_DGV_STATUS_VOLUME
, _MCISTR_int
);
771 ITEM2("window", "handle", MCI_DGV_STATUS_HWND
, _MCISTR_int
);
772 ITEM2("window", "visible", MCI_DGV_STATUS_WINDOW_VISIBLE
, _MCISTR_bool
);
773 ITEM2("window", "minimized", MCI_DGV_STATUS_WINDOW_MINIMIZED
, _MCISTR_bool
);
774 ITEM2("window", "maximized",MCI_DGV_STATUS_WINDOW_MAXIMIZED
, _MCISTR_bool
);
777 FIXME("unknown keyword '%s'\n", keywords
[i
]);
780 if (!pU
->statusParams
.dwItem
)
781 return MCIERR_MISSING_STRING_ARGUMENT
;
783 res
= mciSendCommandA(wDevID
, MCI_STATUS
, dwFlags
, (DWORD
)pU
);
786 _MCISTR_convreturn(type
, pU
->statusParams
.dwReturn
, lpstrReturnString
, uReturnLength
, uDevTyp
, timef
);
795 /* set specified parameters in respective MCI drivers
797 * "door open" eject media or somesuch
798 * "door close" load media
799 * "time format <timeformatname>" "ms" "milliseconds" "msf" "hmsf"
800 * "tmsf" "SMPTE 24" "SMPTE 25" "SMPTE 30"
802 * "audio [all|left|right] [on|off]" sets specified audiochannel on or off
803 * "video [on|off]" sets video on/off
805 * "formattag pcm" sets format to pcm
806 * "formattag <nr>" sets integer formattag value
807 * "any input" accept input from any known source
808 * "any output" output to any known destination
809 * "input <nr>" input from source <nr>
810 * "output <nr>" output to destination <nr>
811 * "channels <nr>" sets nr of channels
812 * "bytespersec <nr>" sets average bytes per second
813 * "samplespersec <nr>" sets average samples per second (1 sample can
815 * "alignment <nr>" sets the blockalignment to <nr>
816 * "bitspersample <nr>" sets the nr of bits per sample
818 * "master [midi|file|smpte|none]" sets the midi master device
819 * "slave [midi|file|smpte|none]" sets the midi master device
820 * "port mapper" midioutput to portmapper
821 * "port <nr>" midioutput to specified port
822 * "tempo <nr>" tempo of track (depends on timeformat/divtype)
823 * "offset <nr>" start offset?
826 MCISTR_Set(_MCISTR_PROTO_
) {
828 MCI_SET_PARMS setParams
;
829 MCI_WAVE_SET_PARMS wavesetParams
;
830 MCI_SEQ_SET_PARMS seqsetParams
;
832 union U
* pU
= xmalloc(sizeof(union U
));
835 pU
->setParams
.dwCallback
= hwndCallback
;
837 for (i
= 0; i
< nrofkeywords
; ) {
838 FLAG2("door", "open", MCI_SET_DOOR_OPEN
);
839 FLAG2("door", "closed", MCI_SET_DOOR_CLOSED
);
841 if (!STRCMP(keywords
[i
], "time") && (i
+2 < nrofkeywords
) && !STRCMP(keywords
[i
+1], "format")) {
842 dwFlags
|= MCI_SET_TIME_FORMAT
;
844 /* FIXME:is this a shortcut for milliseconds or
845 * minutes:seconds? */
846 if (!STRCMP(keywords
[i
+2], "ms"))
847 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
849 if (!STRCMP(keywords
[i
+2], "milliseconds"))
850 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
851 if (!STRCMP(keywords
[i
+2], "msf"))
852 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MSF
;
853 if (!STRCMP(keywords
[i
+2], "hms"))
854 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_HMS
;
855 if (!STRCMP(keywords
[i
+2], "frames"))
856 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_FRAMES
;
857 if (!STRCMP(keywords
[i
+2], "track"))
858 pU
->setParams
.dwTimeFormat
= MCI_VD_FORMAT_TRACK
;
859 if (!STRCMP(keywords
[i
+2], "bytes"))
860 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_BYTES
;
861 if (!STRCMP(keywords
[i
+2], "samples"))
862 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SAMPLES
;
863 if (!STRCMP(keywords
[i
+2], "tmsf"))
864 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_TMSF
;
865 if ( !STRCMP(keywords
[i
+2], "song") &&
866 (i
+3 < nrofkeywords
) &&
867 !STRCMP(keywords
[i
+3], "pointer")
869 pU
->setParams
.dwTimeFormat
= MCI_SEQ_FORMAT_SONGPTR
;
870 if (!STRCMP(keywords
[i
+2], "smpte") && (i
+3 < nrofkeywords
)) {
871 if (!STRCMP(keywords
[i
+3], "24"))
872 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_24
;
873 if (!STRCMP(keywords
[i
+3], "25"))
874 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_25
;
875 if (!STRCMP(keywords
[i
+3], "30"))
876 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30
;
877 if (!STRCMP(keywords
[i
+3], "drop") && (i
+4 < nrofkeywords
) && !STRCMP(keywords
[i
+4], "30")) {
878 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30DROP
;
887 if (!STRCMP(keywords
[i
], "audio") && (i
+1 < nrofkeywords
)) {
888 dwFlags
|= MCI_SET_AUDIO
;
889 if (!STRCMP(keywords
[i
+1], "all"))
890 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_ALL
;
891 if (!STRCMP(keywords
[i
+1], "left"))
892 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_LEFT
;
893 if (!STRCMP(keywords
[i
+1], "right"))
894 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_RIGHT
;
898 FLAG1("video", MCI_SET_VIDEO
);
899 FLAG1("on", MCI_SET_ON
);
900 FLAG1("off", MCI_SET_OFF
);
902 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
903 FLAG2("any", "input", MCI_WAVE_SET_ANYINPUT
);
904 FLAG2("any", "output", MCI_WAVE_SET_ANYOUTPUT
);
906 if ( !STRCMP(keywords
[i
], "formattag") &&
907 (i
+1 < nrofkeywords
) &&
908 !STRCMP(keywords
[i
+1], "pcm")
910 dwFlags
|= MCI_WAVE_SET_FORMATTAG
;
911 pU
->wavesetParams
.wFormatTag
= WAVE_FORMAT_PCM
;
916 /* <keyword> <integer> */
917 #define WII(str,flag,fmt,element) \
918 if (!STRCMP(keywords[i], str) && \
919 (i+1 < nrofkeywords)) { \
920 sscanf(keywords[i+1], fmt, \
921 &(pU->wavesetParams. element)); \
926 WII("formattag", MCI_WAVE_SET_FORMATTAG
, "%u", wFormatTag
);
927 WII("channels", MCI_WAVE_SET_CHANNELS
, "%u", nChannels
);
928 WII("bytespersec", MCI_WAVE_SET_AVGBYTESPERSEC
, "%lu", nAvgBytesPerSec
);
929 WII("samplespersec", MCI_WAVE_SET_SAMPLESPERSEC
, "%lu", nSamplesPerSec
);
930 WII("alignment", MCI_WAVE_SET_BLOCKALIGN
, "%u", nBlockAlign
);
931 WII("bitspersample", MCI_WAVE_SET_BITSPERSAMPLE
, "%u", wBitsPerSample
);
932 WII("input", MCI_WAVE_INPUT
, "%u", wInput
);
933 WII("output", MCI_WAVE_OUTPUT
, "%u", wOutput
);
936 case MCI_DEVTYPE_SEQUENCER
:
937 if (!STRCMP(keywords
[i
], "master") && (i
+1 < nrofkeywords
)) {
938 dwFlags
|= MCI_SEQ_SET_MASTER
;
939 if (!STRCMP(keywords
[i
+1], "midi"))
940 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
941 if (!STRCMP(keywords
[i
+1], "file"))
942 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
943 if (!STRCMP(keywords
[i
+1], "smpte"))
944 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
945 if (!STRCMP(keywords
[i
+1], "none"))
946 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
950 if (!STRCMP(keywords
[i
], "slave") && (i
+1 < nrofkeywords
)) {
951 dwFlags
|= MCI_SEQ_SET_SLAVE
;
952 if (!STRCMP(keywords
[i
+1], "midi"))
953 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
954 if (!STRCMP(keywords
[i
+1], "file"))
955 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
956 if (!STRCMP(keywords
[i
+1], "smpte"))
957 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
958 if (!STRCMP(keywords
[i
+1], "none"))
959 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
963 if ( !STRCMP(keywords
[i
], "port") &&
964 (i
+1 < nrofkeywords
) &&
965 !STRCMP(keywords
[i
+1], "mapper")
967 pU
->seqsetParams
.dwPort
=-1;/* FIXME:not sure*/
968 dwFlags
|= MCI_SEQ_SET_PORT
;
972 #define SII(str,flag,element) \
973 if (!STRCMP(keywords[i], str) && \
974 (i+1 < nrofkeywords)) { \
975 sscanf(keywords[i+1], "%ld", \
976 &(pU->seqsetParams.element));\
981 SII("tempo", MCI_SEQ_SET_TEMPO
, dwTempo
);
982 SII("port", MCI_SEQ_SET_PORT
, dwPort
);
983 SII("offset", MCI_SEQ_SET_PORT
, dwOffset
);
989 return MCIERR_MISSING_STRING_ARGUMENT
;
990 res
= mciSendCommandA(wDevID
, MCI_SET
, dwFlags
, (DWORD
)pU
);
997 * "off" disable break
998 * "on <keyid>" enable break on key with keyid
999 * (I strongly suspect, that there is another parameter:
1001 * but I don't see it mentioned in my documentation.
1005 MCISTR_Break(_MCISTR_PROTO_
)
1007 LPMCI_BREAK_PARMS breakParams
= xmalloc(sizeof(MCI_BREAK_PARMS
));
1010 if (!breakParams
) return 0;
1012 breakParams
->dwCallback
= hwndCallback
;
1013 /*breakParams.hwndBreak ? */
1014 for (i
= 0; i
< nrofkeywords
; i
++) {
1015 FLAG1("off", MCI_BREAK_OFF
);
1016 if (!STRCMP(keywords
[i
], "on") && (nrofkeywords
> i
+1)) {
1017 dwFlags
&= ~MCI_BREAK_OFF
;
1018 dwFlags
|= MCI_BREAK_KEY
;
1019 sscanf(keywords
[i
+1], "%d", &(breakParams
->nVirtKey
));
1024 res
= mciSendCommandA(wDevID
, MCI_BREAK
, dwFlags
, (DWORD
)breakParams
);
1029 #define ITEM1(str, item, xtype) \
1030 if (!STRCMP(keywords[i], str)) { \
1031 gdcParams->dwItem = item; \
1036 #define ITEM2(str1, str2, item, xtype) \
1037 if ( !STRCMP(keywords[i], str1) && \
1038 (i+1 < nrofkeywords) && \
1039 !STRCMP(keywords[i+1], str2)) { \
1040 gdcParams->dwItem = item; \
1045 #define ITEM3(str1, str2, str3, item, xtype) \
1046 if ( !STRCMP(keywords[i], str1) && \
1047 (i+2 < nrofkeywords) && \
1048 !STRCMP(keywords[i+1], str2) && \
1049 !STRCMP(keywords[i+2], str3)) { \
1050 gdcParams->dwItem = item; \
1056 /* get device capabilities of MCI drivers
1059 * "device type" returns device name as string
1060 * "has audio" returns bool
1061 * "has video" returns bool
1062 * "uses files" returns bool
1063 * "compound device" returns bool
1064 * "can record" returns bool
1065 * "can play" returns bool
1066 * "can eject" returns bool
1067 * "can save" returns bool
1069 * "palettes" returns nr of available palette entries
1070 * "windows" returns nr of available windows
1071 * "can reverse" returns bool
1072 * "can stretch" returns bool
1073 * "slow play rate" returns the slow playrate
1074 * "fast play rate" returns the fast playrate
1075 * "normal play rate" returns the normal playrate
1077 * "can freeze" returns bool
1078 * "can lock" returns bool
1079 * "can reverse" returns bool
1080 * "can stretch" returns bool
1081 * "can stretch input" returns bool
1082 * "can test" returns bool
1083 * "has still" returns bool
1084 * "maximum play rate" returns the maximum play rate, in fps
1085 * "minimum play rate" returns the minimum play rate, in fps
1086 * "uses files" returns bool
1087 * "uses palettes" returns bool
1088 * "windows" returns nr of available windows
1090 * "windows" returns nr of available windows
1091 * "can stretch" returns bool
1092 * "can freeze" returns bool
1094 * "cav" assume CAV discs (default if no disk inserted)
1095 * "clv" assume CLV discs
1096 * "can reverse" returns bool
1097 * "slow play rate" returns the slow playrate
1098 * "fast play rate" returns the fast playrate
1099 * "normal play rate" returns the normal playrate
1101 * "inputs" returns nr of inputdevices
1102 * "outputs" returns nr of outputdevices
1105 MCISTR_Capability(_MCISTR_PROTO_
) {
1106 MCI_GETDEVCAPS_PARMS
*gdcParams
= xmalloc(sizeof(MCI_GETDEVCAPS_PARMS
));
1109 gdcParams
->dwCallback
= hwndCallback
;
1111 return MCIERR_MISSING_STRING_ARGUMENT
;
1112 /* well , thats default */
1113 dwFlags
|= MCI_GETDEVCAPS_ITEM
;
1114 gdcParams
->dwItem
= 0;
1116 for (i
= 0; i
< nrofkeywords
; i
++) {
1117 ITEM2("device", "type", MCI_GETDEVCAPS_DEVICE_TYPE
, _MCISTR_devtype
);
1118 ITEM2("has", "audio", MCI_GETDEVCAPS_HAS_AUDIO
, _MCISTR_bool
);
1119 ITEM2("has", "video", MCI_GETDEVCAPS_HAS_VIDEO
, _MCISTR_bool
);
1120 ITEM2("uses", "files", MCI_GETDEVCAPS_USES_FILES
, _MCISTR_bool
);
1121 ITEM2("compound", "device", MCI_GETDEVCAPS_COMPOUND_DEVICE
, _MCISTR_bool
);
1122 ITEM2("can", "record", MCI_GETDEVCAPS_CAN_RECORD
, _MCISTR_bool
);
1123 ITEM2("can", "play", MCI_GETDEVCAPS_CAN_PLAY
, _MCISTR_bool
);
1124 ITEM2("can", "eject", MCI_GETDEVCAPS_CAN_EJECT
, _MCISTR_bool
);
1125 ITEM2("can", "save", MCI_GETDEVCAPS_CAN_SAVE
, _MCISTR_bool
);
1127 case MCI_DEVTYPE_ANIMATION
:
1128 ITEM1("palettes", MCI_ANIM_GETDEVCAPS_PALETTES
, _MCISTR_int
);
1129 ITEM1("windows", MCI_ANIM_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1130 ITEM2("can", "reverse", MCI_ANIM_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1131 ITEM2("can", "stretch", MCI_ANIM_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1132 ITEM3("slow", "play", "rate", MCI_ANIM_GETDEVCAPS_SLOW_RATE
, _MCISTR_int
);
1133 ITEM3("fast", "play", "rate", MCI_ANIM_GETDEVCAPS_FAST_RATE
, _MCISTR_int
);
1134 ITEM3("normal", "play", "rate", MCI_ANIM_GETDEVCAPS_NORMAL_RATE
, _MCISTR_int
);
1136 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1137 ITEM2("can", "freeze", MCI_DGV_GETDEVCAPS_CAN_FREEZE
, _MCISTR_bool
);
1138 ITEM2("can", "lock", MCI_DGV_GETDEVCAPS_CAN_LOCK
, _MCISTR_bool
);
1139 ITEM2("can", "reverse", MCI_DGV_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1140 ITEM3("can", "stretch", "input", MCI_DGV_GETDEVCAPS_CAN_STR_IN
, _MCISTR_bool
);
1141 ITEM2("can", "stretch", MCI_DGV_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1142 ITEM2("can", "test", MCI_DGV_GETDEVCAPS_CAN_TEST
, _MCISTR_bool
);
1143 ITEM2("has", "still", MCI_DGV_GETDEVCAPS_HAS_STILL
, _MCISTR_bool
);
1144 ITEM3("maximum", "play", "rate", MCI_DGV_GETDEVCAPS_MAXIMUM_RATE
, _MCISTR_int
);
1145 ITEM3("minimum", "play", "rate", MCI_DGV_GETDEVCAPS_MINIMUM_RATE
, _MCISTR_int
);
1146 ITEM2("uses", "files", MCI_GETDEVCAPS_USES_FILES
, _MCISTR_bool
);
1147 ITEM2("uses", "palettes", MCI_DGV_GETDEVCAPS_PALETTES
, _MCISTR_bool
);
1148 ITEM1("windows", MCI_DGV_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1150 case MCI_DEVTYPE_OVERLAY
:
1151 ITEM1("windows", MCI_OVLY_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1152 ITEM2("can", "freeze", MCI_OVLY_GETDEVCAPS_CAN_FREEZE
, _MCISTR_bool
);
1153 ITEM2("can", "stretch", MCI_OVLY_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1155 case MCI_DEVTYPE_VIDEODISC
:
1156 FLAG1("cav", MCI_VD_GETDEVCAPS_CAV
);
1157 FLAG1("clv", MCI_VD_GETDEVCAPS_CLV
);
1158 ITEM2("can", "reverse", MCI_VD_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1159 ITEM3("slow", "play", "rate", MCI_VD_GETDEVCAPS_SLOW_RATE
, _MCISTR_int
);
1160 ITEM3("fast", "play", "rate", MCI_VD_GETDEVCAPS_FAST_RATE
, _MCISTR_int
);
1161 ITEM3("normal", "play", "rate", MCI_VD_GETDEVCAPS_NORMAL_RATE
, _MCISTR_int
);
1163 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
1164 ITEM1("inputs", MCI_WAVE_GETDEVCAPS_INPUTS
, _MCISTR_int
);
1165 ITEM1("outputs", MCI_WAVE_GETDEVCAPS_OUTPUTS
, _MCISTR_int
);
1169 res
= mciSendCommandA(wDevID
, MCI_GETDEVCAPS
, dwFlags
, (DWORD
)gdcParams
);
1171 /* no timeformat needed */
1173 _MCISTR_convreturn(type
, gdcParams
->dwReturn
, lpstrReturnString
,
1174 uReturnLength
, uDevTyp
, 0);
1181 /* resumes operation of device. no arguments, no return values */
1183 MCISTR_Resume(_MCISTR_PROTO_
)
1185 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1188 genParams
->dwCallback
= hwndCallback
;
1189 res
= mciSendCommandA(wDevID
, MCI_RESUME
, dwFlags
, (DWORD
)genParams
);
1194 /* pauses operation of device. no arguments, no return values */
1196 MCISTR_Pause(_MCISTR_PROTO_
)
1198 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1201 genParams
->dwCallback
= hwndCallback
;
1202 res
= mciSendCommandA(wDevID
, MCI_PAUSE
, dwFlags
, (DWORD
)genParams
);
1207 /* stops operation of device. no arguments, no return values */
1209 MCISTR_Stop(_MCISTR_PROTO_
)
1211 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1214 genParams
->dwCallback
= hwndCallback
;
1215 res
= mciSendCommandA(wDevID
, MCI_STOP
, dwFlags
, (DWORD
)genParams
);
1220 /* starts recording.
1222 * "overwrite" overwrite existing things
1223 * "insert" insert at current position
1224 * "to <time>" record up to <time> (specified in timeformat)
1225 * "from <time>" record from <time> (specified in timeformat)
1228 MCISTR_Record(_MCISTR_PROTO_
) {
1229 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1231 MCI_RECORD_PARMS
*recordParams
= xmalloc(sizeof(MCI_RECORD_PARMS
));
1233 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1234 if (res
) return res
;
1237 case MCI_FORMAT_MILLISECONDS
:
1238 case MCI_FORMAT_FRAMES
:
1239 case MCI_FORMAT_BYTES
:
1240 case MCI_FORMAT_SAMPLES
:
1244 case MCI_FORMAT_HMS
:
1245 case MCI_FORMAT_MSF
:
1246 parsestr
="%d:%d:%d";
1249 case MCI_FORMAT_TMSF
:
1250 parsestr
="%d:%d:%d:%d";
1253 default:FIXME("unknown timeformat %d, please report.\n", timef
);
1258 recordParams
->dwCallback
= hwndCallback
;
1259 for (i
= 0; i
< nrofkeywords
; ) {
1260 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1262 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1263 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1264 /* add up all integers we got, if we have more
1265 * shift them. (Well I should use the macros in
1266 * mmsystem.h, right).
1268 recordParams
->dwTo
= 0;
1269 for (k
= 0; k
< j
; k
++)
1270 recordParams
->dwTo
+= a
[k
] << (8*(nrargs
-k
));
1274 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1275 dwFlags
|= MCI_FROM
;
1276 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1277 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1279 recordParams
->dwFrom
= 0;
1280 for (k
= 0; k
< j
; k
++)
1281 recordParams
->dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1285 FLAG1("insert", MCI_RECORD_INSERT
);
1286 FLAG1("overwrite", MCI_RECORD_OVERWRITE
);
1289 res
= mciSendCommandA(wDevID
, MCI_RECORD
, dwFlags
, (DWORD
)recordParams
);
1296 * "to <time>" play up to <time> (specified in set timeformat)
1297 * "from <time>" play from <time> (specified in set timeformat)
1301 * "scan" play as fast as possible (with audio disabled perhaps)
1302 * "reverse" play reverse
1303 * "speed <fps>" play with specified frames per second
1307 * "scan" play as fast as possible (with audio disabled perhaps)
1308 * "reverse" play reverse
1309 * "speed <fps>" play with specified frames per second
1317 MCISTR_Play(_MCISTR_PROTO_
) {
1318 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1321 MCI_PLAY_PARMS playParams
;
1322 MCI_VD_PLAY_PARMS vdplayParams
;
1323 MCI_ANIM_PLAY_PARMS animplayParams
;
1324 MCI_DGV_PLAY_PARMS dgvplayParams
;
1326 union U
*pU
= xmalloc(sizeof(union U
));
1328 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1329 if (res
) return res
;
1331 case MCI_FORMAT_MILLISECONDS
:
1332 case MCI_FORMAT_FRAMES
:
1333 case MCI_FORMAT_BYTES
:
1334 case MCI_FORMAT_SAMPLES
:
1338 case MCI_FORMAT_HMS
:
1339 case MCI_FORMAT_MSF
:
1340 parsestr
="%d:%d:%d";
1343 case MCI_FORMAT_TMSF
:
1344 parsestr
="%d:%d:%d:%d";
1347 default:FIXME("unknown timeformat %d, please report.\n", timef
);
1352 pU
->playParams
.dwCallback
= hwndCallback
;
1353 for (i
= 0; i
< nrofkeywords
; ) {
1354 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1356 a
[0]=a
[1]=a
[2]=a
[3]=0;
1357 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1358 /* add up all integers we got, if we have more
1359 * shift them. (Well I should use the macros in
1360 * mmsystem.h, right).
1362 pU
->playParams
.dwTo
=0;
1363 for (k
= 0; k
< j
; k
++)
1364 pU
->playParams
.dwTo
+= a
[k
] << (8*(nrargs
-k
));
1368 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1369 dwFlags
|= MCI_FROM
;
1370 a
[0]=a
[1]=a
[2]=a
[3]=0;
1371 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1373 pU
->playParams
.dwFrom
=0;
1374 for (k
= 0; k
< j
; k
++)
1375 pU
->playParams
.dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1380 case MCI_DEVTYPE_VIDEODISC
:
1381 FLAG1("slow", MCI_VD_PLAY_SLOW
);
1382 FLAG1("fast", MCI_VD_PLAY_FAST
);
1383 FLAG1("scan", MCI_VD_PLAY_SCAN
);
1384 FLAG1("reverse", MCI_VD_PLAY_REVERSE
);
1385 if (!STRCMP(keywords
[i
], "speed") && (i
+1 < nrofkeywords
)) {
1386 dwFlags
|= MCI_VD_PLAY_SPEED
;
1387 sscanf(keywords
[i
+1], "%ld", &(pU
->vdplayParams
.dwSpeed
));
1392 case MCI_DEVTYPE_ANIMATION
:
1393 FLAG1("slow", MCI_ANIM_PLAY_SLOW
);
1394 FLAG1("fast", MCI_ANIM_PLAY_FAST
);
1395 FLAG1("scan", MCI_ANIM_PLAY_SCAN
);
1396 FLAG1("reverse", MCI_ANIM_PLAY_REVERSE
);
1397 if (!STRCMP(keywords
[i
], "speed") && (i
+1 < nrofkeywords
)) {
1398 dwFlags
|= MCI_ANIM_PLAY_SPEED
;
1399 sscanf(keywords
[i
+1], "%ld", &(pU
->animplayParams
.dwSpeed
));
1404 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1405 /* EPP FLAG1("fullscreen", MCI_MCIAVI_PLAY_FULLSCREEN); */
1406 FLAG1("repeat", MCI_DGV_PLAY_REPEAT
);
1407 FLAG1("reverse", MCI_DGV_PLAY_REVERSE
);
1408 /* EPP FLAG1("window", MCI_MCIAVI_PLAY_WINDOW); */
1413 res
= mciSendCommandA(wDevID
, MCI_PLAY
, dwFlags
, (DWORD
)pU
);
1418 /* seek to a specified position
1420 * "to start" seek to start of medium
1421 * "to end" seek to end of medium
1422 * "to <time>" seek to <time> specified in current timeformat
1425 MCISTR_Seek(_MCISTR_PROTO_
) {
1426 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1428 MCI_SEEK_PARMS
*seekParams
= xmalloc(sizeof(MCI_SEEK_PARMS
));
1430 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1431 if (res
) return res
;
1433 case MCI_FORMAT_MILLISECONDS
:
1434 case MCI_FORMAT_FRAMES
:
1435 case MCI_FORMAT_BYTES
:
1436 case MCI_FORMAT_SAMPLES
:
1440 case MCI_FORMAT_HMS
:
1441 case MCI_FORMAT_MSF
:
1442 parsestr
="%d:%d:%d";
1445 case MCI_FORMAT_TMSF
:
1446 parsestr
="%d:%d:%d:%d";
1450 FIXME("unknown timeformat %d, please report.\n", timef
);
1455 seekParams
->dwCallback
= hwndCallback
;
1456 for (i
= 0; i
< nrofkeywords
; ) {
1457 if (!STRCMP(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1458 if (!STRCMP(keywords
[i
+1], "start")) {
1459 dwFlags
|= MCI_SEEK_TO_START
;
1460 seekParams
->dwTo
= 0;
1464 if (!STRCMP(keywords
[i
+1], "end")) {
1465 dwFlags
|= MCI_SEEK_TO_END
;
1466 seekParams
->dwTo
= 0;
1472 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1473 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1474 seekParams
->dwTo
= 0;
1475 for (k
= 0; k
< j
; k
++)
1476 seekParams
->dwTo
+= a
[k
] << (8*(nrargs
-k
));
1480 case MCI_DEVTYPE_VIDEODISC
:
1481 FLAG1("reverse", MCI_VD_SEEK_REVERSE
);
1486 res
= mciSendCommandA(wDevID
, MCI_SEEK
, dwFlags
, (DWORD
)seekParams
);
1491 /* close media/driver */
1493 MCISTR_Close(_MCISTR_PROTO_
)
1495 MCI_GENERIC_PARMS
* closeParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1498 closeParams
->dwCallback
= hwndCallback
;
1499 res
= mciSendCommandA(wDevID
, MCI_CLOSE
, dwFlags
, (DWORD
)closeParams
);
1504 /* return information.
1506 * "product" return product name (human readable)
1507 * "file" return filename
1509 * "text" returns text?
1511 * "text" returns text?
1524 MCISTR_Info(_MCISTR_PROTO_
)
1527 MCI_INFO_PARMSA infoParams
;
1528 MCI_DGV_INFO_PARMSA dgvinfoParams
;
1530 union U
* pU
= xmalloc(sizeof(union U
));
1535 for (i
= 0; i
< nrofkeywords
; i
++) {
1536 FLAG1("product", MCI_INFO_PRODUCT
);
1537 FLAG1("file", MCI_INFO_FILE
);
1539 case MCI_DEVTYPE_ANIMATION
:
1540 FLAG2("window", "text", MCI_ANIM_INFO_TEXT
);
1542 case MCI_DEVTYPE_OVERLAY
:
1543 FLAG2("window", "text", MCI_OVLY_INFO_TEXT
);
1545 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1546 #define MI1(str, flag) \
1547 if (!STRCMP(keywords[i], str)) { \
1548 dwFlags |= MCI_DGV_INFO_ITEM; \
1549 pU->dgvinfoParams.dwItem |= flag; \
1553 #define MI2(str1, str2, flag) \
1554 if (!STRCMP(keywords[i], str1) && \
1555 (i+1 < nrofkeywords) && \
1556 !STRCMP(keywords[i+1], str2)) { \
1557 dwFlags |= MCI_DGV_INFO_ITEM; \
1558 pU->dgvinfoParams.dwItem |= flag; \
1562 MI2("audio", "algorithm", MCI_DGV_INFO_AUDIO_ALG
);
1563 MI2("audio", "quality", MCI_DGV_INFO_AUDIO_QUALITY
);
1564 MI2("still", "algorithm", MCI_DGV_INFO_STILL_ALG
);
1565 MI2("still", "quality", MCI_DGV_INFO_STILL_QUALITY
);
1566 MI1("usage", MCI_DGV_INFO_USAGE
);
1567 MI1("version", MCI_INFO_VERSION
);
1568 MI2("video", "algorithm", MCI_DGV_INFO_VIDEO_ALG
);
1569 MI2("video", "quality", MCI_DGV_INFO_VIDEO_QUALITY
);
1570 MI2("window", "text", MCI_DGV_INFO_TEXT
);
1575 if (dwFlags
== sflags
)
1576 return MCIERR_MISSING_STRING_ARGUMENT
;
1577 pU
->infoParams
.dwCallback
= hwndCallback
;
1579 /* MCI driver will fill in lpstrReturn, dwRetSize.
1580 * FIXME: I don't know if this is correct behaviour
1582 res
= mciSendCommandA(wDevID
, MCI_INFO
, dwFlags
, (DWORD
)pU
);
1584 _MCI_STR(pU
->infoParams
.lpstrReturn
);
1589 /* query MCI driver itself for information
1591 * "installname" return install name of <device> (system.ini)
1592 * "quantity" return nr of installed drivers
1593 * "open" open drivers only (additional flag)
1594 * "name <nr>" return nr of devices with <devicetyp>
1595 * "name all" return nr of all devices
1599 MCISTR_Sysinfo(_MCISTR_PROTO_
) {
1600 MCI_SYSINFO_PARMSA sysinfoParams
;
1603 sysinfoParams
.lpstrReturn
= lpstrReturnString
;
1604 sysinfoParams
.dwRetSize
= uReturnLength
;
1605 sysinfoParams
.wDeviceType
= uDevTyp
;
1606 sysinfoParams
.dwCallback
= hwndCallback
;
1608 for (i
= 0; i
< nrofkeywords
; i
++) {
1609 FLAG1("installname", MCI_SYSINFO_INSTALLNAME
);
1610 FLAG1("quantity", MCI_SYSINFO_INSTALLNAME
);
1611 FLAG1("open", MCI_SYSINFO_OPEN
);
1612 if (!strcmp(keywords
[i
], "name") && (i
+1 < nrofkeywords
)) {
1613 sscanf(keywords
[i
+1], "%ld", &(sysinfoParams
.dwNumber
));
1614 dwFlags
|= MCI_SYSINFO_NAME
;
1618 res
= mciSendCommandA(0, MCI_SYSINFO
, dwFlags
, (DWORD
)&sysinfoParams
);
1620 if (dwFlags
& MCI_SYSINFO_QUANTITY
) {
1623 sprintf(buf
, "%ld", *(long*)lpstrReturnString
);
1626 /* no need to copy anything back, mciSysInfo did it for us */
1631 * Argument: "<filename>"
1632 * Overlay: "at <left> <top> <right> <bottom>" additional
1635 MCISTR_Load(_MCISTR_PROTO_
) {
1637 MCI_LOAD_PARMSA loadParams
;
1638 MCI_OVLY_LOAD_PARMSA ovlyloadParams
;
1640 union U
*pU
= xmalloc(sizeof(union U
));
1641 int i
, len
= 0, res
;
1644 for (i
= 0; i
< nrofkeywords
; ) {
1646 case MCI_DEVTYPE_OVERLAY
:
1647 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1648 dwFlags
|= MCI_OVLY_RECT
;
1649 sscanf(keywords
[i
+1], "%d", &(pU
->ovlyloadParams
.rc
.left
));
1650 sscanf(keywords
[i
+2], "%d", &(pU
->ovlyloadParams
.rc
.top
));
1651 sscanf(keywords
[i
+3], "%d", &(pU
->ovlyloadParams
.rc
.right
));
1652 sscanf(keywords
[i
+4], "%d", &(pU
->ovlyloadParams
.rc
.bottom
));
1653 memcpy(keywords
+i
, keywords
+(i
+5), nrofkeywords
-(i
+5));
1658 len
+= strlen(keywords
[i
])+1;
1661 s
=(char*)xmalloc(len
);
1663 while (i
< nrofkeywords
) {
1664 strcat(s
, keywords
[i
]);
1666 if (i
< nrofkeywords
) strcat(s
, " ");
1668 pU
->loadParams
.lpfilename
= s
;
1669 pU
->loadParams
.dwCallback
= hwndCallback
;
1670 dwFlags
|= MCI_LOAD_FILE
;
1671 res
= mciSendCommandA(wDevID
, MCI_LOAD
, dwFlags
, (DWORD
)pU
);
1678 * Argument: "<filename>"
1679 * Overlay: "at <left> <top> <right> <bottom>" additional
1682 MCISTR_Save(_MCISTR_PROTO_
) {
1684 MCI_SAVE_PARMS saveParams
;
1685 MCI_OVLY_SAVE_PARMSA ovlysaveParams
;
1687 union U
* pU
= xmalloc(sizeof(union U
));
1688 int i
, len
= 0, res
;
1691 for (i
= 0; i
< nrofkeywords
; ) {
1693 case MCI_DEVTYPE_OVERLAY
:
1694 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1695 dwFlags
|= MCI_OVLY_RECT
;
1696 sscanf(keywords
[i
+1], "%d", &(pU
->ovlysaveParams
.rc
.left
));
1697 sscanf(keywords
[i
+2], "%d", &(pU
->ovlysaveParams
.rc
.top
));
1698 sscanf(keywords
[i
+3], "%d", &(pU
->ovlysaveParams
.rc
.right
));
1699 sscanf(keywords
[i
+4], "%d", &(pU
->ovlysaveParams
.rc
.bottom
));
1700 memcpy(keywords
+i
, keywords
+(i
+5), nrofkeywords
-(i
+5));
1705 len
+= strlen(keywords
[i
])+1;
1708 s
= (char*)xmalloc(len
);
1710 while (i
< nrofkeywords
) {
1711 strcat(s
, keywords
[i
]);
1713 if (i
< nrofkeywords
) strcat(s
, " ");
1715 pU
->saveParams
.lpfilename
= s
;
1716 pU
->saveParams
.dwCallback
= hwndCallback
;
1717 dwFlags
|= MCI_LOAD_FILE
;
1718 res
= mciSendCommandA(wDevID
, MCI_SAVE
, dwFlags
, (DWORD
)pU
);
1724 /* prepare device for input/output
1725 * (only applyable to waveform audio)
1728 MCISTR_Cue(_MCISTR_PROTO_
) {
1729 MCI_GENERIC_PARMS
*cueParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1732 for (i
= 0; i
< nrofkeywords
; i
++) {
1734 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
1735 FLAG1("input", MCI_WAVE_INPUT
);
1736 FLAG1("output", MCI_WAVE_OUTPUT
);
1741 cueParams
->dwCallback
= hwndCallback
;
1743 res
= mciSendCommandA(wDevID
, MCI_CUE
, dwFlags
, (DWORD
)cueParams
);
1748 /* delete information */
1750 MCISTR_Delete(_MCISTR_PROTO_
) {
1751 int timef
, nrargs
, i
, j
, k
, a
[4], res
;
1753 MCI_WAVE_DELETE_PARMS
*deleteParams
= xmalloc(sizeof(MCI_WAVE_DELETE_PARMS
));
1755 /* only implemented for waveform audio */
1756 if (uDevTyp
!= MCI_DEVTYPE_WAVEFORM_AUDIO
)
1757 return MCIERR_UNSUPPORTED_FUNCTION
; /* well it fits */
1758 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1759 if (res
) return res
;
1761 case MCI_FORMAT_MILLISECONDS
:
1762 case MCI_FORMAT_FRAMES
:
1763 case MCI_FORMAT_BYTES
:
1764 case MCI_FORMAT_SAMPLES
:
1768 case MCI_FORMAT_HMS
:
1769 case MCI_FORMAT_MSF
:
1770 parsestr
="%d:%d:%d";
1773 case MCI_FORMAT_TMSF
:
1774 parsestr
="%d:%d:%d:%d";
1777 default:FIXME("unknown timeformat %d, please report.\n", timef
);
1782 for (i
= 0; i
< nrofkeywords
; ) {
1783 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1785 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1786 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1787 /* add up all integers we got, if we have more
1788 * shift them. (Well I should use the macros in
1789 * mmsystem.h, right).
1791 deleteParams
->dwTo
= 0;
1792 for (k
= 0;k
< j
;k
++)
1793 deleteParams
->dwTo
+= a
[k
]<<(8*(nrargs
-k
));
1797 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1798 dwFlags
|= MCI_FROM
;
1799 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1800 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1802 deleteParams
->dwFrom
= 0;
1803 for (k
= 0; k
< j
; k
++)
1804 deleteParams
->dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1810 deleteParams
->dwCallback
= hwndCallback
;
1811 res
= mciSendCommandA(wDevID
, MCI_DELETE
, dwFlags
, (DWORD
)deleteParams
);
1816 /* send command to device. only applies to videodisc */
1818 MCISTR_Escape(_MCISTR_PROTO_
)
1820 LPMCI_VD_ESCAPE_PARMSA escapeParams
= xmalloc(sizeof(MCI_VD_ESCAPE_PARMSA
));
1821 int i
, len
= 0, res
;
1824 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
1825 return MCIERR_UNSUPPORTED_FUNCTION
;
1827 for (i
= 0; i
< nrofkeywords
; i
++) {
1828 len
+= strlen(keywords
[i
]) + 1;
1830 s
= (char*)malloc(len
);
1832 for (i
= 0; i
< nrofkeywords
; ) {
1833 strcat(s
, keywords
[i
]);
1835 if (i
< nrofkeywords
) strcat(s
, " ");
1837 escapeParams
->lpstrCommand
= s
;
1838 escapeParams
->dwCallback
= hwndCallback
;
1839 dwFlags
|= MCI_VD_ESCAPE_STRING
;
1840 res
= mciSendCommandA(wDevID
, MCI_ESCAPE
, dwFlags
, (DWORD
)escapeParams
);
1846 /* unfreeze [part of] the overlayed video
1847 * only applyable to Overlay devices
1850 MCISTR_Unfreeze(_MCISTR_PROTO_
)
1852 LPMCI_OVLY_RECT_PARMS unfreezeParams
= xmalloc(sizeof(MCI_OVLY_RECT_PARMS
));
1855 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1856 return MCIERR_UNSUPPORTED_FUNCTION
;
1857 for (i
= 0; i
< nrofkeywords
; ) {
1858 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1859 sscanf(keywords
[i
+1], "%d", &(unfreezeParams
->rc
.left
));
1860 sscanf(keywords
[i
+2], "%d", &(unfreezeParams
->rc
.top
));
1861 sscanf(keywords
[i
+3], "%d", &(unfreezeParams
->rc
.right
));
1862 sscanf(keywords
[i
+4], "%d", &(unfreezeParams
->rc
.bottom
));
1863 dwFlags
|= MCI_OVLY_RECT
;
1869 unfreezeParams
->dwCallback
= hwndCallback
;
1870 res
= mciSendCommandA(wDevID
, MCI_UNFREEZE
, dwFlags
, (DWORD
)unfreezeParams
);
1871 free(unfreezeParams
);
1874 /* freeze [part of] the overlayed video
1875 * only applyable to Overlay devices
1878 MCISTR_Freeze(_MCISTR_PROTO_
)
1880 LPMCI_OVLY_RECT_PARMS freezeParams
= xmalloc(sizeof(MCI_OVLY_RECT_PARMS
));
1883 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1884 return MCIERR_UNSUPPORTED_FUNCTION
;
1885 for (i
= 0; i
< nrofkeywords
; ) {
1886 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1887 sscanf(keywords
[i
+1], "%d", &(freezeParams
->rc
.left
));
1888 sscanf(keywords
[i
+2], "%d", &(freezeParams
->rc
.top
));
1889 sscanf(keywords
[i
+3], "%d", &(freezeParams
->rc
.right
));
1890 sscanf(keywords
[i
+4], "%d", &(freezeParams
->rc
.bottom
));
1891 dwFlags
|= MCI_OVLY_RECT
;
1897 freezeParams
->dwCallback
= hwndCallback
;
1898 res
= mciSendCommandA(wDevID
, MCI_FREEZE
, dwFlags
, (DWORD
)freezeParams
);
1903 /* copy parts of image to somewhere else
1904 * "source [at <left> <top> <right> <bottom>]" source is framebuffer [or rect]
1905 * "destination [at <left> <top> <right> <bottom>]" destination is framebuffer [or rect]
1907 * "frame [at <left> <top> <right> <bottom>]" frame is framebuffer [or rect]
1908 * where the video input is placed
1909 * "video [at <left> <top> <right> <bottom>]" video is whole video [or rect]
1910 * (defining part of input to
1912 * FIXME: This whole junk is passing multiple rectangles.
1913 * I don't know how to do that with the present interface.
1914 * (Means code below is broken)
1917 MCISTR_Put(_MCISTR_PROTO_
) {
1919 MCI_OVLY_RECT_PARMS ovlyputParams
;
1920 MCI_ANIM_RECT_PARMS animputParams
;
1921 MCI_DGV_RECT_PARMS dgvputParams
;
1923 union U
* pU
= xmalloc(sizeof(union U
));
1926 for (i
= 0; i
< nrofkeywords
; ) {
1928 case MCI_DEVTYPE_ANIMATION
:
1929 FLAG1("source", MCI_ANIM_PUT_SOURCE
);
1930 FLAG1("destination", MCI_ANIM_PUT_DESTINATION
);
1931 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1932 sscanf(keywords
[i
+1], "%d", &(pU
->animputParams
.rc
.left
));
1933 sscanf(keywords
[i
+2], "%d", &(pU
->animputParams
.rc
.top
));
1934 sscanf(keywords
[i
+3], "%d", &(pU
->animputParams
.rc
.right
));
1935 sscanf(keywords
[i
+4], "%d", &(pU
->animputParams
.rc
.bottom
));
1936 dwFlags
|= MCI_ANIM_RECT
;
1941 case MCI_DEVTYPE_OVERLAY
:
1942 FLAG1("source", MCI_OVLY_PUT_SOURCE
);
1943 FLAG1("destination", MCI_OVLY_PUT_DESTINATION
);
1944 FLAG1("video", MCI_OVLY_PUT_VIDEO
);
1945 FLAG1("frame", MCI_OVLY_PUT_FRAME
);
1946 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1947 sscanf(keywords
[i
+1], "%d", &(pU
->ovlyputParams
.rc
.left
));
1948 sscanf(keywords
[i
+2], "%d", &(pU
->ovlyputParams
.rc
.top
));
1949 sscanf(keywords
[i
+3], "%d", &(pU
->ovlyputParams
.rc
.right
));
1950 sscanf(keywords
[i
+4], "%d", &(pU
->ovlyputParams
.rc
.bottom
));
1951 dwFlags
|= MCI_OVLY_RECT
;
1956 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1957 FLAG1("source", MCI_DGV_PUT_SOURCE
);
1958 FLAG1("destination", MCI_DGV_PUT_DESTINATION
);
1959 FLAG1("video", MCI_DGV_PUT_VIDEO
);
1960 FLAG1("frame", MCI_DGV_PUT_FRAME
);
1961 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1962 sscanf(keywords
[i
+1], "%d", &(pU
->dgvputParams
.rc
.left
));
1963 sscanf(keywords
[i
+2], "%d", &(pU
->dgvputParams
.rc
.top
));
1964 sscanf(keywords
[i
+3], "%d", &(pU
->dgvputParams
.rc
.right
));
1965 sscanf(keywords
[i
+4], "%d", &(pU
->dgvputParams
.rc
.bottom
));
1966 dwFlags
|= MCI_DGV_RECT
;
1975 pU
->dgvputParams
.dwCallback
= hwndCallback
;
1976 res
= mciSendCommandA(wDevID
, MCI_PUT
, dwFlags
, (DWORD
)pU
);
1981 /* palette behaviour changing
1983 * "normal" realize the palette normally
1984 * "background" realize the palette as background palette
1987 MCISTR_Realize(_MCISTR_PROTO_
)
1989 MCI_GENERIC_PARMS
*realizeParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1992 if (uDevTyp
!= MCI_DEVTYPE_ANIMATION
)
1993 return MCIERR_UNSUPPORTED_FUNCTION
;
1994 for (i
= 0; i
< nrofkeywords
; i
++) {
1995 FLAG1("background", MCI_ANIM_REALIZE_BKGD
);
1996 FLAG1("normal", MCI_ANIM_REALIZE_NORM
);
1998 realizeParams
->dwCallback
= hwndCallback
;
1999 res
= mciSendCommandA(wDevID
, MCI_REALIZE
, dwFlags
, (DWORD
)realizeParams
);
2000 free(realizeParams
);
2005 * "algorithm <algorithm>"
2006 * "alignment to <integer>"
2007 * "bass to <factor>"
2008 * "bitspersample to <bit_count>"
2009 * "bytespersec to <integer>"
2014 * "left volume to <factor>"
2019 * "quality <descripto>r"
2024 * "right volume to <factor>"
2025 * "samplespersec to <integer>"
2026 * "source to <sourcename>"
2027 * "stream to <number>"
2028 * "treble to <factor>"
2029 * "volume to <factor>"
2033 * "monitor to type number number"
2035 * "record track track_number off"
2037 * "record track track_number on "
2038 * "source to type number number"
2039 * "track track_number off"
2040 * "track track_number on"
2043 MCISTR_SetAudio(_MCISTR_PROTO_
)
2045 MCI_DGV_SETAUDIO_PARMSA setaudioParams
;
2048 if (uDevTyp
!= MCI_DEVTYPE_DIGITAL_VIDEO
)
2049 return MCIERR_UNSUPPORTED_FUNCTION
;
2051 setaudioParams
.dwCallback
= hwndCallback
;
2053 for (i
= 0; i
< nrofkeywords
; ) {
2054 if (!STRCMP(keywords
[i
], "algorithm") && (i
+1 < nrofkeywords
)) {
2055 setaudioParams
.lpstrAlgorithm
= strdup(keywords
[i
+1]);
2056 dwFlags
|= MCI_DGV_SETAUDIO_ALG
;
2060 #define MSAI2(str1, str2, flag) \
2061 if ( !STRCMP(keywords[i], str1) && (i+2 < nrofkeywords) && \
2062 !STRCMP(keywords[i+1], str2)) { \
2063 dwFlags |= MCI_DGV_SETAUDIO_ITEM; \
2064 setaudioParams.dwItem = flag; \
2065 sscanf(keywords[i+2], "%lu", &setaudioParams.dwValue); \
2069 #define MSAI3(str1, str2, str3, flag) \
2070 if ( !STRCMP(keywords[i], str1) && (i+3 < nrofkeywords) && \
2071 !STRCMP(keywords[i+1], str2) && !STRCMP(keywords[i+2], str3)) { \
2072 dwFlags |= MCI_DGV_SETAUDIO_ITEM; \
2073 setaudioParams.dwItem = flag; \
2074 sscanf(keywords[i+3], "%lu", &setaudioParams.dwValue); \
2078 MSAI2("alignment", "to", MCI_DGV_SETAUDIO_BLOCKALIGN
);
2079 MSAI2("bass", "to", MCI_DGV_SETAUDIO_BASS
);
2080 MSAI2("bitspersample", "to", MCI_DGV_SETAUDIO_BITSPERSAMPLE
);
2081 MSAI2("bytespersec", "to", MCI_DGV_SETAUDIO_AVGBYTESPERSEC
);
2082 MSAI2("samplespersec", "to", MCI_DGV_SETAUDIO_SAMPLESPERSEC
);
2083 MSAI2("stream", "to", MCI_DGV_SETAUDIO_STREAM
);
2084 MSAI2("treble", "to", MCI_DGV_SETAUDIO_TREBLE
);
2085 MSAI2("volume", "to", MCI_DGV_SETAUDIO_VOLUME
);
2086 MSAI3("input", "bass", "to", MCI_DGV_SETAUDIO_BASS
|MCI_DGV_SETAUDIO_INPUT
);
2087 MSAI3("input", "treble", "to", MCI_DGV_SETAUDIO_TREBLE
|MCI_DGV_SETAUDIO_INPUT
);
2088 MSAI3("input", "volume", "to", MCI_DGV_SETAUDIO_VOLUME
|MCI_DGV_SETAUDIO_INPUT
);
2089 MSAI3("output", "bass", "to", MCI_DGV_SETAUDIO_BASS
|MCI_DGV_SETAUDIO_OUTPUT
);
2090 MSAI3("output", "treble", "to", MCI_DGV_SETAUDIO_TREBLE
|MCI_DGV_SETAUDIO_OUTPUT
);
2091 MSAI3("output", "volume", "to", MCI_DGV_SETAUDIO_VOLUME
|MCI_DGV_SETAUDIO_OUTPUT
);
2093 FLAG1("clocktime", MCI_DGV_SETAUDIO_CLOCKTIME
);
2094 FLAG2("left", "off", MCI_DGV_SETAUDIO_LEFT
|MCI_SET_OFF
);
2095 FLAG2("left", "on", MCI_DGV_SETAUDIO_LEFT
|MCI_SET_ON
);
2096 if (!STRCMP(keywords
[i
], "left") && (i
+3 < nrofkeywords
) &&
2097 !STRCMP(keywords
[i
+1], "volume") && !STRCMP(keywords
[i
+2], "to")) {
2098 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
| MCI_DGV_SETAUDIO_VALUE
| MCI_DGV_SETAUDIO_LEFT
;
2099 setaudioParams
.dwItem
= MCI_DGV_SETAUDIO_VOLUME
;
2100 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwValue
);
2104 FLAG1("off", MCI_SET_OFF
);
2105 FLAG1("on", MCI_SET_ON
);
2106 if (!STRCMP(keywords
[i
], "over") && (i
+1 < nrofkeywords
)) {
2107 dwFlags
|= MCI_DGV_SETAUDIO_OVER
;
2108 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwOver
);
2112 if (!STRCMP(keywords
[i
], "quality") && (i
+1 < nrofkeywords
)) {
2113 setaudioParams
.lpstrQuality
= strdup(keywords
[i
+1]);
2114 dwFlags
|= MCI_DGV_SETAUDIO_QUALITY
;
2118 FLAG2("record", "off", MCI_DGV_SETAUDIO_RECORD
|MCI_SET_OFF
);
2119 FLAG2("record", "on", MCI_DGV_SETAUDIO_RECORD
|MCI_SET_ON
);
2120 FLAG2("right", "off", MCI_DGV_SETAUDIO_RIGHT
|MCI_SET_OFF
);
2121 FLAG2("right", "on", MCI_DGV_SETAUDIO_RIGHT
|MCI_SET_ON
);
2122 if (!STRCMP(keywords
[i
], "right") && (i
+3 < nrofkeywords
) &&
2123 !STRCMP(keywords
[i
+1], "volume") && !STRCMP(keywords
[i
+2], "to")) {
2124 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
| MCI_DGV_SETAUDIO_VALUE
| MCI_DGV_SETAUDIO_RIGHT
;
2125 setaudioParams
.dwItem
= MCI_DGV_SETAUDIO_VOLUME
;
2126 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwValue
);
2130 if (!STRCMP(keywords
[i
], "source") && (i
+2 < nrofkeywords
) && !STRCMP(keywords
[i
+1], "to")) {
2131 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
;
2132 setaudioParams
.dwItem
|= MCI_DGV_SETAUDIO_SOURCE
;
2133 if (!STRCMP(keywords
[i
+2], "left")) {
2134 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_LEFT
;
2135 } else if (!STRCMP(keywords
[i
+2], "right")) {
2136 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_RIGHT
;
2137 } else if (!STRCMP(keywords
[i
+2], "average")) {
2138 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_AVERAGE
;
2139 } else if (!STRCMP(keywords
[i
+2], "stereo")) {
2140 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_STEREO
;
2142 res
= MCIERR_UNSUPPORTED_FUNCTION
;
2149 res
= mciSendCommandA(wDevID
, MCI_SETAUDIO
, dwFlags
, (DWORD
)&setaudioParams
);
2150 free(setaudioParams
.lpstrAlgorithm
);
2151 free(setaudioParams
.lpstrQuality
);
2155 /* videodisc spinning
2160 MCISTR_Spin(_MCISTR_PROTO_
)
2162 MCI_GENERIC_PARMS
*spinParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
2165 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
2166 return MCIERR_UNSUPPORTED_FUNCTION
;
2167 for (i
= 0; i
< nrofkeywords
; i
++) {
2168 FLAG1("up", MCI_VD_SPIN_UP
);
2169 FLAG1("down", MCI_VD_SPIN_UP
);
2171 spinParams
->dwCallback
= hwndCallback
;
2172 res
= mciSendCommandA(wDevID
, MCI_SPIN
, dwFlags
, (DWORD
)spinParams
);
2177 /* step single frames
2178 * "reverse" optional flag
2179 * "by <nr>" for <nr> frames
2182 MCISTR_Step(_MCISTR_PROTO_
) {
2184 MCI_ANIM_STEP_PARMS animstepParams
;
2185 MCI_VD_STEP_PARMS vdstepParams
;
2187 union U
*pU
= xmalloc(sizeof(union U
));
2190 for (i
= 0; i
< nrofkeywords
; ) {
2192 case MCI_DEVTYPE_ANIMATION
:
2193 FLAG1("reverse", MCI_ANIM_STEP_REVERSE
);
2194 if (!STRCMP(keywords
[i
], "by") && (i
+1 < nrofkeywords
)) {
2195 sscanf(keywords
[i
+1], "%ld", &(pU
->animstepParams
.dwFrames
));
2196 dwFlags
|= MCI_ANIM_STEP_FRAMES
;
2201 case MCI_DEVTYPE_VIDEODISC
:
2202 FLAG1("reverse", MCI_VD_STEP_REVERSE
);
2203 if (!STRCMP(keywords
[i
], "by") && (i
+1 < nrofkeywords
)) {
2204 sscanf(keywords
[i
+1], "%ld", &(pU
->vdstepParams
.dwFrames
));
2205 dwFlags
|= MCI_VD_STEP_FRAMES
;
2213 pU
->animstepParams
.dwCallback
= hwndCallback
;
2214 res
= mciSendCommandA(wDevID
, MCI_STEP
, dwFlags
, (DWORD
)pU
);
2219 /* update animation window
2221 * "at <left> <top> <right> <bottom>" only in this rectangle
2222 * "hdc" device context
2225 MCISTR_Update(_MCISTR_PROTO_
) {
2227 LPMCI_ANIM_UPDATE_PARMS updateParams
= xmalloc(sizeof(MCI_ANIM_UPDATE_PARMS
));
2229 for (i
= 0; i
< nrofkeywords
; ) {
2230 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
2231 sscanf(keywords
[i
+1], "%d", &(updateParams
->rc
.left
));
2232 sscanf(keywords
[i
+2], "%d", &(updateParams
->rc
.top
));
2233 sscanf(keywords
[i
+3], "%d", &(updateParams
->rc
.right
));
2234 sscanf(keywords
[i
+4], "%d", &(updateParams
->rc
.bottom
));
2235 dwFlags
|= MCI_ANIM_RECT
;
2239 if (!STRCMP(keywords
[i
], "hdc") && (i
+1 < nrofkeywords
)) {
2240 dwFlags
|= MCI_ANIM_UPDATE_HDC
;
2241 sscanf(keywords
[i
+1], "%d", &(updateParams
->hDC
));
2247 updateParams
->dwCallback
= hwndCallback
;
2248 res
= mciSendCommandA(wDevID
, MCI_UPDATE
, dwFlags
, (DWORD
)updateParams
);
2253 /* where command for animation and overlay drivers.
2254 * just returns the specified rectangle as a string
2263 MCISTR_Where(_MCISTR_PROTO_
) {
2265 MCI_ANIM_RECT_PARMS animwhereParams
;
2266 MCI_OVLY_RECT_PARMS ovlywhereParams
;
2268 union U
* pU
= xmalloc(sizeof(union U
));
2271 for (i
= 0; i
< nrofkeywords
; i
++) {
2273 case MCI_DEVTYPE_ANIMATION
:
2274 FLAG1("source", MCI_ANIM_WHERE_SOURCE
);
2275 FLAG1("destination", MCI_ANIM_WHERE_DESTINATION
);
2277 case MCI_DEVTYPE_OVERLAY
:
2278 FLAG1("source", MCI_OVLY_WHERE_SOURCE
);
2279 FLAG1("destination", MCI_OVLY_WHERE_DESTINATION
);
2280 FLAG1("video", MCI_OVLY_WHERE_VIDEO
);
2281 FLAG1("frame", MCI_OVLY_WHERE_FRAME
);
2285 pU
->animwhereParams
.dwCallback
= hwndCallback
;
2286 res
= mciSendCommandA(wDevID
, MCI_WHERE
, dwFlags
, (DWORD
)pU
);
2290 case MCI_DEVTYPE_ANIMATION
:
2291 sprintf(buf
, "%d %d %d %d",
2292 pU
->animwhereParams
.rc
.left
,
2293 pU
->animwhereParams
.rc
.top
,
2294 pU
->animwhereParams
.rc
.right
,
2295 pU
->animwhereParams
.rc
.bottom
2298 case MCI_DEVTYPE_OVERLAY
:
2299 sprintf(buf
, "%d %d %d %d",
2300 pU
->ovlywhereParams
.rc
.left
,
2301 pU
->ovlywhereParams
.rc
.top
,
2302 pU
->ovlywhereParams
.rc
.right
,
2303 pU
->ovlywhereParams
.rc
.bottom
2306 default:strcpy(buf
, "0 0 0 0");break;
2315 MCISTR_Window(_MCISTR_PROTO_
) {
2317 MCI_ANIM_WINDOW_PARMSA animwindowParams
;
2318 MCI_OVLY_WINDOW_PARMSA ovlywindowParams
;
2319 MCI_DGV_WINDOW_PARMSA dgvwindowParams
;
2321 union U
* pU
= xmalloc(sizeof(union U
));
2326 for (i
= 0; i
< nrofkeywords
; ) {
2328 case MCI_DEVTYPE_ANIMATION
:
2329 if (!STRCMP(keywords
[i
], "handle") && (i
+1 < nrofkeywords
)) {
2330 dwFlags
|= MCI_ANIM_WINDOW_HWND
;
2331 if (!STRCMP(keywords
[i
+1], "default"))
2332 pU
->animwindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
2334 sscanf(keywords
[i
+1], "%d", &(pU
->animwindowParams
.hWnd
));
2338 if (!STRCMP(keywords
[i
], "state") && (i
+1 < nrofkeywords
)) {
2339 dwFlags
|= MCI_ANIM_WINDOW_STATE
;
2340 if (!STRCMP(keywords
[i
+1], "hide"))
2341 pU
->animwindowParams
.nCmdShow
= SW_HIDE
;
2342 if (!STRCMP(keywords
[i
+1], "iconic"))
2343 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2344 if (!STRCMP(keywords
[i
+1], "minimized"))
2345 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2346 if (!STRCMP(keywords
[i
+1], "maximized"))
2347 pU
->animwindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2348 if (!STRCMP(keywords
[i
+1], "minimize"))
2349 pU
->animwindowParams
.nCmdShow
= SW_MINIMIZE
;
2350 if (!STRCMP(keywords
[i
+1], "normal"))
2351 pU
->animwindowParams
.nCmdShow
= SW_NORMAL
;
2352 if (!STRCMP(keywords
[i
+1], "restore"))
2353 pU
->animwindowParams
.nCmdShow
= SW_NORMAL
;
2354 if (!STRCMP(keywords
[i
+1], "show"))
2355 pU
->animwindowParams
.nCmdShow
= SW_SHOW
;
2356 if (!STRCMP(keywords
[i
+1], "no") && (i
+2 < nrofkeywords
)) {
2357 if (!STRCMP(keywords
[i
+2], "active"))
2358 pU
->animwindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2359 if (!STRCMP(keywords
[i
+2], "action"))
2360 pU
->animwindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2366 /* text is enclosed in " ... " as it seems */
2367 if (!STRCMP(keywords
[i
], "text")) {
2368 if (keywords
[i
+1][0] != '"') {
2372 dwFlags
|= MCI_ANIM_WINDOW_TEXT
;
2373 pU
->animwindowParams
.lpstrText
= _MCISTR_Unquote(keywords
[i
+1]);
2377 FLAG1("stretch", MCI_ANIM_WINDOW_ENABLE_STRETCH
);
2379 case MCI_DEVTYPE_DIGITAL_VIDEO
:
2380 if (!STRCMP(keywords
[i
], "handle") && (i
+1 < nrofkeywords
)) {
2381 dwFlags
|= MCI_DGV_WINDOW_HWND
;
2382 if (!STRCMP(keywords
[i
+1], "default"))
2383 pU
->dgvwindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
2385 sscanf(keywords
[i
+1], "%d", &(pU
->dgvwindowParams
.hWnd
));
2389 if (!STRCMP(keywords
[i
], "state") && (i
+1 < nrofkeywords
)) {
2390 dwFlags
|= MCI_DGV_WINDOW_STATE
;
2391 if (!STRCMP(keywords
[i
+1], "hide"))
2392 pU
->dgvwindowParams
.nCmdShow
= SW_HIDE
;
2393 if (!STRCMP(keywords
[i
+1], "iconic"))
2394 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2395 if (!STRCMP(keywords
[i
+1], "minimized"))
2396 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2397 if (!STRCMP(keywords
[i
+1], "maximized"))
2398 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2399 if (!STRCMP(keywords
[i
+1], "minimize"))
2400 pU
->dgvwindowParams
.nCmdShow
= SW_MINIMIZE
;
2401 if (!STRCMP(keywords
[i
+1], "normal"))
2402 pU
->dgvwindowParams
.nCmdShow
= SW_NORMAL
;
2403 if (!STRCMP(keywords
[i
+1], "restore"))
2404 pU
->dgvwindowParams
.nCmdShow
= SW_NORMAL
;
2405 if (!STRCMP(keywords
[i
+1], "show"))
2406 pU
->dgvwindowParams
.nCmdShow
= SW_SHOW
;
2407 if (!STRCMP(keywords
[i
+1], "no") && (i
+2 < nrofkeywords
)) {
2408 if (!STRCMP(keywords
[i
+2], "active"))
2409 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2410 if (!STRCMP(keywords
[i
+2], "action"))
2411 pU
->dgvwindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2417 /* text is enclosed in " ... " as it seems */
2418 if (!STRCMP(keywords
[i
], "text")) {
2419 if (keywords
[i
+1][0] != '"') {
2423 dwFlags
|= MCI_DGV_WINDOW_TEXT
;
2424 pU
->dgvwindowParams
.lpstrText
= _MCISTR_Unquote(keywords
[i
+1]);
2430 case MCI_DEVTYPE_OVERLAY
:
2431 if (!STRCMP(keywords
[i
], "handle") && (i
+1 < nrofkeywords
)) {
2432 dwFlags
|= MCI_OVLY_WINDOW_HWND
;
2433 if (!STRCMP(keywords
[i
+1], "default"))
2434 pU
->ovlywindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
2436 sscanf(keywords
[i
+1], "%d", &(pU
->ovlywindowParams
.hWnd
));
2440 if (!STRCMP(keywords
[i
], "state") && (i
+1 < nrofkeywords
)) {
2441 dwFlags
|= MCI_OVLY_WINDOW_STATE
;
2442 if (!STRCMP(keywords
[i
+1], "hide"))
2443 pU
->ovlywindowParams
.nCmdShow
= SW_HIDE
;
2444 if (!STRCMP(keywords
[i
+1], "iconic"))
2445 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2446 if (!STRCMP(keywords
[i
+1], "minimized"))
2447 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2448 if (!STRCMP(keywords
[i
+1], "maximized"))
2449 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2450 if (!STRCMP(keywords
[i
+1], "minimize"))
2451 pU
->ovlywindowParams
.nCmdShow
= SW_MINIMIZE
;
2452 if (!STRCMP(keywords
[i
+1], "normal"))
2453 pU
->ovlywindowParams
.nCmdShow
= SW_NORMAL
;
2454 if (!STRCMP(keywords
[i
+1], "show"))
2455 pU
->ovlywindowParams
.nCmdShow
= SW_SHOW
;
2456 if (!STRCMP(keywords
[i
+1], "no") && (i
+2 < nrofkeywords
)) {
2457 if (!STRCMP(keywords
[i
+2], "active"))
2458 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2459 if (!STRCMP(keywords
[i
+2], "action"))
2460 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2466 /* text is enclosed in " ... " as it seems */
2467 if (!STRCMP(keywords
[i
], "text")) {
2468 if (keywords
[i
+1][0] != '"') {
2472 dwFlags
|= MCI_OVLY_WINDOW_TEXT
;
2473 pU
->ovlywindowParams
.lpstrText
= _MCISTR_Unquote(keywords
[i
+1]);
2477 FLAG1("stretch", MCI_OVLY_WINDOW_ENABLE_STRETCH
);
2482 pU
->animwindowParams
.dwCallback
= hwndCallback
;
2483 res
= mciSendCommandA(wDevID
, MCI_WINDOW
, dwFlags
, (DWORD
)pU
);
2489 struct _MCISTR_cmdtable
{
2491 DWORD (*fun
)(_MCISTR_PROTO_
);
2492 } MCISTR_cmdtable
[]={
2493 {"break", MCISTR_Break
},
2494 {"capability", MCISTR_Capability
},
2495 {"close", MCISTR_Close
},
2496 {"cue", MCISTR_Cue
},
2497 {"delete", MCISTR_Delete
},
2498 {"escape", MCISTR_Escape
},
2499 {"freeze", MCISTR_Freeze
},
2500 {"info", MCISTR_Info
},
2501 {"load", MCISTR_Load
},
2502 {"open", MCISTR_Open
},
2503 {"pause", MCISTR_Pause
},
2504 {"play", MCISTR_Play
},
2505 {"put", MCISTR_Put
},
2506 {"realize", MCISTR_Realize
},
2507 {"record", MCISTR_Record
},
2508 {"resume", MCISTR_Resume
},
2509 {"save", MCISTR_Save
},
2510 {"seek", MCISTR_Seek
},
2511 {"set", MCISTR_Set
},
2512 {"setaudio", MCISTR_SetAudio
},
2513 {"spin", MCISTR_Spin
},
2514 {"status", MCISTR_Status
},
2515 {"step", MCISTR_Step
},
2516 {"stop", MCISTR_Stop
},
2517 {"sysinfo", MCISTR_Sysinfo
},
2518 {"unfreeze", MCISTR_Unfreeze
},
2519 {"update", MCISTR_Update
},
2520 {"where", MCISTR_Where
},
2521 {"window", MCISTR_Window
},
2525 /**************************************************************************
2526 * mciSendString16 [MMSYSTEM.702]
2528 /* The usercode sends a string with a command (and flags) expressed in
2529 * words in it... We do our best to call appropriate drivers,
2530 * and return a errorcode AND a readable string (if lpstrRS != NULL)
2531 * Info gathered by watching cool134.exe and from Borland's mcistrwh.hlp
2533 /* FIXME: "all" is a valid devicetype and we should access all devices if
2534 * it is used. (imagine "close all"). Not implemented yet.
2536 DWORD WINAPI
mciSendString16(LPCSTR lpstrCommand
, LPSTR lpstrReturnString
,
2537 UINT16 uReturnLength
, HWND16 hwndCallback
)
2539 char *cmd
, *dev
, *args
, **keywords
;
2540 WORD uDevTyp
= 0, wDevID
= 0;
2542 int res
= 0, i
, nrofkeywords
;
2544 TRACE("('%s', %p, %d, %X)\n",
2545 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2547 /* format is <command> <device> <optargs> */
2548 cmd
= strdup(lpstrCommand
);
2549 dev
= strchr(cmd
, ' ');
2552 return MCIERR_MISSING_DEVICE_NAME
;
2555 args
= strchr(dev
, ' ');
2561 while (*++args
== ' ');
2563 i
= 1;/* nrofkeywords = nrofspaces+1 */
2565 while ((s
= strchr(s
, ' ')) != NULL
) {
2567 while (*++s
== ' ');
2568 /* see if we have a quoted string */
2570 s
= strchr(s
+1, '"');
2571 if (!s
|| s
[1] != ' ') {
2572 /* missed closing '"'*/
2574 return MCIERR_NO_CLOSING_QUOTE
;
2578 keywords
= (char**)xmalloc(sizeof(char*) * (i
+ 2));
2582 while (s
&& i
< nrofkeywords
) {
2585 if ((s
= strchr(s
+1, '"')) != NULL
) s
++;
2591 while (*++s
== ' ');
2593 TRACE("[%d] => '%s'\n", i
-1, keywords
[i
-1]);
2598 keywords
= (char**)xmalloc(sizeof(char*));
2601 dwFlags
= 0; /* default flags */
2602 for (i
= 0; i
< nrofkeywords
;) {
2603 if (!STRCMP(keywords
[i
], "wait")) {
2604 dwFlags
|= MCI_WAIT
;
2605 memcpy(keywords
+i
, keywords
+(i
+1), (nrofkeywords
-i
-1) * sizeof(char*));
2609 if (!STRCMP(keywords
[i
], "notify")) {
2610 dwFlags
|= MCI_NOTIFY
;
2611 memcpy(keywords
+i
, keywords
+(i
+1), (nrofkeywords
-i
-1) * sizeof(char*));
2618 /* determine wDevID and uDevTyp for all commands except "open" */
2619 if (STRCMP(cmd
, "open") != 0) {
2620 wDevID
= mciGetDeviceIDA(dev
);
2622 TRACE("Device '%s' not found!\n", dev
);
2623 res
= MCIERR_INVALID_DEVICE_NAME
;
2626 uDevTyp
= MCI_GetDriver(wDevID
)->wType
;
2629 if (lpstrReturnString
&& uReturnLength
> 0)
2630 *lpstrReturnString
= 0;
2632 for (i
= 0; MCISTR_cmdtable
[i
].cmd
!= NULL
; i
++) {
2633 if (!STRCMP(MCISTR_cmdtable
[i
].cmd
, cmd
)) {
2634 res
= MCISTR_cmdtable
[i
].fun(wDevID
, uDevTyp
, lpstrReturnString
,
2635 uReturnLength
, dev
, (LPSTR
*)keywords
,
2636 nrofkeywords
, dwFlags
, hwndCallback
);
2640 if (MCISTR_cmdtable
[i
].cmd
== NULL
) {
2641 FIXME("('%s', %p, %u, %X): unimplemented, please report.\n",
2642 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2643 res
= MCIERR_MISSING_COMMAND_STRING
;
2646 TRACE("=> %d [%s]\n", res
, lpstrReturnString
);
2647 free(keywords
); free(cmd
);
2651 /**************************************************************************
2652 * mciSendStringA [MMSYSTEM.702][WINMM.51]
2654 DWORD WINAPI
mciSendStringA(LPCSTR lpstrCommand
, LPSTR lpstrReturnString
,
2655 UINT uReturnLength
, HWND hwndCallback
)
2657 return mciSendString16(lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2660 /**************************************************************************
2661 * mciSendStringW [WINMM.52]
2663 DWORD WINAPI
mciSendStringW(LPCWSTR lpwstrCommand
, LPSTR lpstrReturnString
,
2664 UINT uReturnLength
, HWND hwndCallback
)
2669 /* FIXME: is there something to do with lpstrReturnString ? */
2670 lpstrCommand
= HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrCommand
);
2671 ret
= mciSendString16(lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2672 HeapFree(GetProcessHeap(), 0, lpstrCommand
);
2676 /**************************************************************************
2677 * mciExecute [WINMM.38]
2679 DWORD WINAPI
mciExecute(LPCSTR lpstrCommand
)
2684 TRACE("(%s)!\n", lpstrCommand
);
2686 ret
= mciSendString16(lpstrCommand
, strRet
, sizeof(strRet
), 0);
2688 if (!mciGetErrorString16(ret
, strRet
, sizeof(strRet
))) {
2689 sprintf(strRet
, "Unknown MCI error (%ld)", ret
);
2691 MessageBoxA(0, strRet
, "Error in mciExecute()", MB_OK
);
2693 /* FIXME: what shall I return ? */