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 static LPSTR
_MCISTR_Unquote(LPSTR str
)
63 int i
, len
= strlen(str
);
65 if (len
> 1 && str
[0] == '"' && str
[len
-1] == '"') {
66 for (i
= 1; i
< len
-1; i
++) {
75 /* print a DWORD in the specified timeformat */
77 _MCISTR_printtf(char *buf
, UINT16 uDevType
, DWORD timef
, DWORD val
)
81 case MCI_FORMAT_MILLISECONDS
:
82 case MCI_FORMAT_FRAMES
:
83 case MCI_FORMAT_BYTES
:
84 case MCI_FORMAT_SAMPLES
:
85 case MCI_VD_FORMAT_TRACK
:
86 /*case MCI_SEQ_FORMAT_SONGPTR: sameas MCI_VD_FORMAT_TRACK */
87 sprintf(buf
, "%ld",val
);
90 /* well, the macros have the same content*/
93 sprintf(buf
, "%d:%d:%d",
99 sprintf(buf
, "%d:%d:%d:%d",
101 MCI_TMSF_MINUTE(val
),
102 MCI_TMSF_SECOND(val
),
103 MCI_TMSF_FRAME(val
));
106 FIXME(mci
, "missing timeformat for %ld, report.\n", timef
);
107 strcpy(buf
, "0"); /* hmm */
112 /* possible different return types */
113 #define _MCISTR_int 1
114 #define _MCISTR_time 2
115 #define _MCISTR_bool 3
116 #define _MCISTR_tfname 4
117 #define _MCISTR_mode 5
118 #define _MCISTR_divtype 6
119 #define _MCISTR_seqtype 7
120 #define _MCISTR_vdmtype 8
121 #define _MCISTR_devtype 9
124 _MCISTR_convreturn(int type
, DWORD dwReturn
, LPSTR lpstrReturnString
,
125 WORD uReturnLength
, WORD uDevTyp
, int timef
)
128 case _MCISTR_vdmtype
:
130 case MCI_VD_MEDIA_CLV
: _MCI_STR("CLV"); break;
131 case MCI_VD_MEDIA_CAV
: _MCI_STR("CAV"); break;
133 case MCI_VD_MEDIA_OTHER
:_MCI_STR("other"); break;
136 case _MCISTR_seqtype
:
138 case MCI_SEQ_NONE
: _MCI_STR("none"); break;
139 case MCI_SEQ_SMPTE
: _MCI_STR("smpte"); break;
140 case MCI_SEQ_FILE
: _MCI_STR("file"); break;
141 case MCI_SEQ_MIDI
: _MCI_STR("midi"); break;
142 default:FIXME(mci
, "missing sequencer mode %ld\n", dwReturn
);
147 case MCI_MODE_NOT_READY
:_MCI_STR("not ready"); break;
148 case MCI_MODE_STOP
: _MCI_STR("stopped"); break;
149 case MCI_MODE_PLAY
: _MCI_STR("playing"); break;
150 case MCI_MODE_RECORD
: _MCI_STR("recording"); break;
151 case MCI_MODE_SEEK
: _MCI_STR("seeking"); break;
152 case MCI_MODE_PAUSE
: _MCI_STR("paused"); break;
153 case MCI_MODE_OPEN
: _MCI_STR("open"); break;
165 sprintf(buf
, "%ld", dwReturn
);
171 _MCISTR_printtf(buf
, uDevTyp
, timef
, dwReturn
);
177 case MCI_FORMAT_MILLISECONDS
: _MCI_STR("milliseconds"); break;
178 case MCI_FORMAT_FRAMES
: _MCI_STR("frames"); break;
179 case MCI_FORMAT_BYTES
: _MCI_STR("bytes"); break;
180 case MCI_FORMAT_SAMPLES
: _MCI_STR("samples"); break;
181 case MCI_FORMAT_HMS
: _MCI_STR("hms"); break;
182 case MCI_FORMAT_MSF
: _MCI_STR("msf"); break;
183 case MCI_FORMAT_TMSF
: _MCI_STR("tmsf"); break;
185 FIXME(mci
, "missing timefmt for %d, report.\n", timef
);
189 case _MCISTR_divtype
:
191 case MCI_SEQ_DIV_PPQN
: _MCI_STR("PPQN"); break;
192 case MCI_SEQ_DIV_SMPTE_24
: _MCI_STR("SMPTE 24 frame"); break;
193 case MCI_SEQ_DIV_SMPTE_25
: _MCI_STR("SMPTE 25 frame"); break;
194 case MCI_SEQ_DIV_SMPTE_30
: _MCI_STR("SMPTE 30 frame"); break;
195 case MCI_SEQ_DIV_SMPTE_30DROP
: _MCI_STR("SMPTE 30 frame drop");break;
197 case _MCISTR_devtype
:
199 case MCI_DEVTYPE_VCR
: _MCI_STR("vcr"); break;
200 case MCI_DEVTYPE_VIDEODISC
: _MCI_STR("videodisc"); break;
201 case MCI_DEVTYPE_CD_AUDIO
: _MCI_STR("cd audio"); break;
202 case MCI_DEVTYPE_OVERLAY
: _MCI_STR("overlay"); break;
203 case MCI_DEVTYPE_DAT
: _MCI_STR("dat"); break;
204 case MCI_DEVTYPE_SCANNER
: _MCI_STR("scanner"); break;
205 case MCI_DEVTYPE_ANIMATION
: _MCI_STR("animation"); break;
206 case MCI_DEVTYPE_DIGITAL_VIDEO
: _MCI_STR("digital video"); break;
207 case MCI_DEVTYPE_OTHER
: _MCI_STR("other"); break;
208 case MCI_DEVTYPE_WAVEFORM_AUDIO
:_MCI_STR("waveform audio"); break;
209 case MCI_DEVTYPE_SEQUENCER
: _MCI_STR("sequencer"); break;
210 default:FIXME(mci
, "unknown device type %ld, report.\n",
215 FIXME(mci
, "unknown resulttype %d, report.\n", type
);
220 #define FLAG1(str, flag) \
221 if (!STRCMP(keywords[i], str)) { \
227 #define FLAG2(str1, str2, flag) \
228 if (!STRCMP(keywords[i], str1) && \
229 (i+1 < nrofkeywords) && \
230 !STRCMP(keywords[i+1], str2)) { \
236 /* All known subcommands are implemented in single functions to avoid
237 * bloat and a xxxx lines long mciSendString(). All commands are of the
238 * format MCISTR_Cmd(_MCISTR_PROTO_) where _MCISTR_PROTO_ is the above
239 * defined line of arguments. (This is just for easy enhanceability.)
240 * All functions return the MCIERR_ errorvalue as DWORD. Returnvalues
241 * for the calls are in lpstrReturnString (If I mention return values
242 * in function headers, I mean returnvalues in lpstrReturnString.)
243 * Integers are sprintf("%d")ed integers. Boolean values are
244 * "true" and "false".
245 * timeformat depending values are "%d" "%d:%d" "%d:%d:%d" "%d:%d:%d:%d"
246 * FIXME: is above line correct?
248 * Preceding every function is a list of implemented/known arguments.
249 * Feel free to add missing arguments.
254 * Opens the specified MCI driver.
258 * "alias <aliasname>"
259 * "element <elementname>"
262 * "buffer <nrBytesPerSec>"
264 * "nostatic" increaste nr of nonstatic colours
265 * "parent <windowhandle>"
266 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
267 * "style child" WS_CHILD
268 * "style overlap" WS_OVERLAPPED
269 * "style popup" WS_POPUP
271 * "parent <windowhandle>"
272 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
273 * "style child" WS_CHILD
274 * "style overlap" WS_OVERLAPPED
275 * "style popup" WS_POPUP
279 MCISTR_Open(_MCISTR_PROTO_
)
284 MCI_OPEN_PARMSA openParams
;
285 MCI_WAVE_OPEN_PARMSA waveopenParams
;
286 MCI_ANIM_OPEN_PARMSA animopenParams
;
287 MCI_OVLY_OPEN_PARMSA ovlyopenParams
;
288 MCI_DGV_OPEN_PARMSA dgvopenParams
;
290 union U
* pU
= xmalloc(sizeof(union U
));
292 pU
->openParams
.lpstrElementName
= NULL
;
293 s
= strchr(dev
, '!');
296 pU
->openParams
.lpstrElementName
= strdup(s
);
297 dwFlags
|= MCI_OPEN_ELEMENT
;
299 for (i
= 0; i
< nrofkeywords
; ) {
300 if ((!STRCMP(keywords
[i
], "type")) && (i
< nrofkeywords
-1)) {
301 pU
->openParams
.lpstrElementName
= strdup(dev
);
302 dwFlags
|= MCI_OPEN_ELEMENT
;
304 /* FIXME: isn't there a memory leak here ? keyword+i ? */
305 memcpy(keywords
+i
, keywords
+(i
+2), (nrofkeywords
-i
-2) * sizeof(char*));
312 CharUpperA((char*)dev
);
313 uDevTyp
= MCI_GetDevTypeFromString(dev
);
315 free(pU
->openParams
.lpstrElementName
);
317 return MCIERR_INVALID_DEVICE_NAME
;
320 pU
->openParams
.dwCallback
= hwndCallback
;
321 pU
->openParams
.wDeviceID
= wDevID
;
322 pU
->ovlyopenParams
.dwStyle
= 0;
323 pU
->animopenParams
.dwStyle
= 0;
324 pU
->openParams
.lpstrDeviceType
= strdup(dev
);
325 pU
->openParams
.lpstrAlias
= NULL
;
326 dwFlags
|= MCI_OPEN_TYPE
;
327 for (i
= 0; i
< nrofkeywords
; ) {
328 FLAG1("shareable", MCI_OPEN_SHAREABLE
);
329 if (!STRCMP(keywords
[i
], "alias") && (i
+1 < nrofkeywords
)) {
330 dwFlags
|= MCI_OPEN_ALIAS
;
331 pU
->openParams
.lpstrAlias
= strdup(keywords
[i
+1]);
335 if (!STRCMP(keywords
[i
], "element") && (i
+1 < nrofkeywords
)) {
336 dwFlags
|= MCI_OPEN_ELEMENT
;
337 assert(pU
->openParams
.lpstrElementName
== NULL
);
338 pU
->openParams
.lpstrElementName
= strdup(keywords
[i
+1]);
343 case MCI_DEVTYPE_ANIMATION
:
344 FLAG1("nostatic", MCI_ANIM_OPEN_NOSTATIC
);
345 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
346 dwFlags
|= MCI_ANIM_OPEN_PARENT
;
347 sscanf(keywords
[i
+1], "%u", &(pU
->animopenParams
.hWndParent
));
351 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
354 dwFlags
|= MCI_ANIM_OPEN_WS
;
355 if (!STRCMP(keywords
[i
+1], "popup")) {
356 pU
->animopenParams
.dwStyle
|= WS_POPUP
;
357 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
358 pU
->animopenParams
.dwStyle
|= WS_OVERLAPPED
;
359 } else if (!STRCMP(keywords
[i
+1], "child")) {
360 pU
->animopenParams
.dwStyle
|= WS_CHILD
;
361 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
362 pU
->animopenParams
.dwStyle
|= st
;
364 FIXME(mci
, "unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
369 case MCI_DEVTYPE_DIGITAL_VIDEO
:
370 FLAG1("nostatic", MCI_ANIM_OPEN_NOSTATIC
);
371 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
372 dwFlags
|= MCI_DGV_OPEN_PARENT
;
373 sscanf(keywords
[i
+1], "%u", &(pU
->dgvopenParams
.hWndParent
));
377 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
380 dwFlags
|= MCI_DGV_OPEN_WS
;
381 if (!STRCMP(keywords
[i
+1], "popup")) {
382 pU
->dgvopenParams
.dwStyle
|= WS_POPUP
;
383 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
384 pU
->dgvopenParams
.dwStyle
|= WS_OVERLAPPED
;
385 } else if (!STRCMP(keywords
[i
+1], "child")) {
386 pU
->dgvopenParams
.dwStyle
|= WS_CHILD
;
387 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
388 pU
->dgvopenParams
.dwStyle
|= st
;
390 FIXME(mci
, "unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
395 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
396 if (!STRCMP(keywords
[i
], "buffer") && (i
+1 < nrofkeywords
)) {
397 dwFlags
|= MCI_WAVE_OPEN_BUFFER
;
398 sscanf(keywords
[i
+1], "%ld", &(pU
->waveopenParams
.dwBufferSeconds
));
401 case MCI_DEVTYPE_OVERLAY
:
402 /* looks just like anim, but without NOSTATIC */
403 if (!STRCMP(keywords
[i
], "parent") && (i
+1 < nrofkeywords
)) {
404 dwFlags
|= MCI_OVLY_OPEN_PARENT
;
405 sscanf(keywords
[i
+1], "%u", &(pU
->ovlyopenParams
.hWndParent
));
409 if (!STRCMP(keywords
[i
], "style") && (i
+1 < nrofkeywords
)) {
412 dwFlags
|= MCI_OVLY_OPEN_WS
;
413 if (!STRCMP(keywords
[i
+1], "popup")) {
414 pU
->ovlyopenParams
.dwStyle
|= WS_POPUP
;
415 } else if (!STRCMP(keywords
[i
+1], "overlap")) {
416 pU
->ovlyopenParams
.dwStyle
|= WS_OVERLAPPED
;
417 } else if (!STRCMP(keywords
[i
+1], "child")) {
418 pU
->ovlyopenParams
.dwStyle
|= WS_CHILD
;
419 } else if (sscanf(keywords
[i
+1], "%ld", &st
)) {
420 pU
->ovlyopenParams
.dwStyle
|= st
;
422 FIXME(mci
, "unknown 'style' keyword %s, please report.\n", keywords
[i
+1]);
428 FIXME(mci
, "unknown parameter passed %s, please report.\n",
433 _MCISTR_Unquote(pU
->openParams
.lpstrElementName
);
435 res
= mciSendCommandA(0, MCI_OPEN
, dwFlags
, (DWORD
)pU
);
437 free(pU
->openParams
.lpstrElementName
);
438 free(pU
->openParams
.lpstrDeviceType
);
439 free(pU
->openParams
.lpstrAlias
);
444 /* A helper function for a lot of others ...
445 * for instance status/play/record/seek etc.
448 _MCISTR_determine_timeformat(LPCSTR dev
, WORD wDevID
, WORD uDevTyp
, int *timef
)
451 DWORD dwFlags
= MCI_STATUS_ITEM
;
452 LPMCI_STATUS_PARMS statusParams
= xmalloc(sizeof(MCI_STATUS_PARMS
));
454 if (!statusParams
) return 0;
455 statusParams
->dwItem
= MCI_STATUS_TIME_FORMAT
;
456 statusParams
->dwReturn
= 0;
457 res
= mciSendCommandA(wDevID
, MCI_STATUS
, dwFlags
, (DWORD
)statusParams
);
459 if (res
== 0) *timef
= statusParams
->dwReturn
;
464 /* query status of MCI drivers
467 * "mode" - returns "not ready" "paused" "playing" "stopped" "open"
468 * "parked" "recording" "seeking" ....
470 * "current track" - returns current track as integer
471 * "length [track <nr>]" - returns length [of track <nr>] in current
473 * "number of tracks" - returns number of tracks as integer
474 * "position [track <nr>]" - returns position [in track <nr>] in current
476 * "ready" - checks if device is ready to play, -> bool
477 * "start position" - returns start position in timeformat
478 * "time format" - returns timeformat (list of possible values:
479 * "ms" "msf" "milliseconds" "hmsf" "tmsf" "frames"
480 * "bytes" "samples" "hms")
481 * "media present" - returns if media is present as bool
483 * "forward" - returns "true" if device is playing forwards
484 * "speed" - returns speed for device
485 * "palette handle" - returns palette handle
486 * "window handle" - returns window handle
487 * "stretch" - returns stretch bool
489 * "division type" - ? returns "PPQN" "SMPTE 24 frame"
490 * "SMPTE 25 frame" "SMPTE 30 frame" "SMPTE 30 drop frame"
491 * "tempo" - current tempo in (PPQN? speed in frames, SMPTE*? speed in hsmf)
492 * "offset" - offset in dito.
493 * "port" - midi port as integer
494 * "slave" - slave device ("midi", "file", "none", "smpte")
495 * "master" - masterdevice (dito.)
497 * "window handle" - see animation
500 * "speed" - speed as integer
501 * "forward" - returns bool (when playing forward)
502 * "side" - returns 1 or 2
503 * "media type" - returns "CAV" "CLV" "other"
504 * "disc size" - returns "8" or "12"
506 * "input" - base queries on input set
507 * "output" - base queries on output set
508 * "format tag" - return integer format tag
509 * "channels" - return integer nr of channels
510 * "bytespersec" - return average nr of bytes/sec
511 * "samplespersec" - return nr of samples per sec
512 * "bitspersample" - return bitspersample
513 * "alignment" - return block alignment
514 * "level" - return level?
518 * "audio bitspersample"
520 * "audio bytespersec"
524 * "audio samplespersec"
545 * "nominal frame rate"
546 * "nominal record frame rate"
551 * "record frame rate"
559 * "still file format"
568 * "video source number"
577 #define ITEM1(str, item, xtype) \
578 if (!STRCMP(keywords[i], str)) { \
579 pU->statusParams.dwItem = item; \
584 #define ITEM2(str1, str2, item, xtype) \
585 if ( !STRCMP(keywords[i], str1) && \
586 (i+1 < nrofkeywords) && \
587 !STRCMP(keywords[i+1], str2)) { \
588 pU->statusParams.dwItem = item; \
593 #define ITEM3(str1, str2, str3, item, xtype) \
594 if ( !STRCMP(keywords[i], str1) && \
595 (i+2 < nrofkeywords) && \
596 !STRCMP(keywords[i+1], str2) && \
597 !STRCMP(keywords[i+2], str3)) { \
598 pU->statusParams.dwItem = item; \
603 #define ITEM4(str1, str2, str3, str4, item, xtype) \
604 if ( !STRCMP(keywords[i], str1) && \
605 (i+3 < nrofkeywords) && \
606 !STRCMP(keywords[i+1], str2) && \
607 !STRCMP(keywords[i+2], str3) && \
608 !STRCMP(keywords[i+3], str4)) { \
609 pU->statusParams.dwItem = item; \
616 MCISTR_Status(_MCISTR_PROTO_
) {
618 MCI_STATUS_PARMS statusParams
;
619 MCI_DGV_STATUS_PARMSA dgvstatusParams
;
621 union U
* pU
= xmalloc(sizeof(union U
));
622 int type
= 0, i
, res
, timef
;
624 pU
->statusParams
.dwCallback
= hwndCallback
;
625 dwFlags
|= MCI_STATUS_ITEM
;
626 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
629 pU
->statusParams
.dwReturn
= 0;
630 pU
->statusParams
.dwItem
= 0;
632 for (i
= 0; i
< nrofkeywords
; ) {
633 if (!STRCMP(keywords
[i
], "track") && (i
+1 < nrofkeywords
)) {
634 sscanf(keywords
[i
+1], "%ld", &(pU
->statusParams
.dwTrack
));
635 dwFlags
|= MCI_TRACK
;
639 FLAG1("start", MCI_STATUS_START
);
641 ITEM2("current", "track", MCI_STATUS_CURRENT_TRACK
, _MCISTR_time
);
642 ITEM2("time", "format", MCI_STATUS_TIME_FORMAT
, _MCISTR_tfname
);
643 ITEM1("ready", MCI_STATUS_READY
, _MCISTR_bool
);
644 ITEM1("mode", MCI_STATUS_MODE
, _MCISTR_mode
);
645 ITEM3("number", "of", "tracks", MCI_STATUS_NUMBER_OF_TRACKS
, _MCISTR_int
);
646 ITEM1("length", MCI_STATUS_LENGTH
, _MCISTR_time
);
647 ITEM1("position", MCI_STATUS_POSITION
, _MCISTR_time
);
648 ITEM2("media", "present", MCI_STATUS_MEDIA_PRESENT
, _MCISTR_bool
);
651 case MCI_DEVTYPE_ANIMATION
:
652 ITEM2("palette", "handle", MCI_ANIM_STATUS_HPAL
, _MCISTR_int
);
653 ITEM2("window", "handle", MCI_ANIM_STATUS_HWND
, _MCISTR_int
);
654 ITEM1("stretch", MCI_ANIM_STATUS_STRETCH
, _MCISTR_bool
);
655 ITEM1("speed", MCI_ANIM_STATUS_SPEED
, _MCISTR_int
);
656 ITEM1("forward", MCI_ANIM_STATUS_FORWARD
, _MCISTR_bool
);
658 case MCI_DEVTYPE_SEQUENCER
:
659 /* just completing the list, not working correctly */
660 ITEM2("division", "type", MCI_SEQ_STATUS_DIVTYPE
, _MCISTR_divtype
);
661 /* tempo ... PPQN in frames/second, SMPTE in hmsf */
662 ITEM1("tempo", MCI_SEQ_STATUS_TEMPO
, _MCISTR_int
);
663 ITEM1("port", MCI_SEQ_STATUS_PORT
, _MCISTR_int
);
664 ITEM1("slave", MCI_SEQ_STATUS_SLAVE
, _MCISTR_seqtype
);
665 ITEM1("master", MCI_SEQ_STATUS_SLAVE
, _MCISTR_seqtype
);
666 /* offset ... PPQN in frames/second, SMPTE in hmsf */
667 ITEM1("offset", MCI_SEQ_STATUS_SLAVE
, _MCISTR_time
);
669 case MCI_DEVTYPE_OVERLAY
:
670 ITEM2("window", "handle", MCI_OVLY_STATUS_HWND
, _MCISTR_int
);
671 ITEM1("stretch", MCI_OVLY_STATUS_STRETCH
, _MCISTR_bool
);
673 case MCI_DEVTYPE_VIDEODISC
:
674 ITEM1("speed", MCI_VD_STATUS_SPEED
, _MCISTR_int
);
675 ITEM1("forward", MCI_VD_STATUS_FORWARD
, _MCISTR_bool
);
676 ITEM1("side", MCI_VD_STATUS_SIDE
, _MCISTR_int
);
677 ITEM2("media", "type", MCI_VD_STATUS_SIDE
, _MCISTR_vdmtype
);
678 /* returns 8 or 12 */
679 ITEM2("disc", "size", MCI_VD_STATUS_DISC_SIZE
, _MCISTR_int
);
681 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
682 /* I am not quite sure if foll. 2 lines are right. */
683 FLAG1("input", MCI_WAVE_INPUT
);
684 FLAG1("output", MCI_WAVE_OUTPUT
);
686 ITEM2("format", "tag", MCI_WAVE_STATUS_FORMATTAG
, _MCISTR_int
);
687 ITEM1("channels", MCI_WAVE_STATUS_CHANNELS
, _MCISTR_int
);
688 ITEM1("bytespersec", MCI_WAVE_STATUS_AVGBYTESPERSEC
, _MCISTR_int
);
689 ITEM1("samplespersec", MCI_WAVE_STATUS_SAMPLESPERSEC
, _MCISTR_int
);
690 ITEM1("bitspersample", MCI_WAVE_STATUS_BITSPERSAMPLE
, _MCISTR_int
);
691 ITEM1("alignment", MCI_WAVE_STATUS_BLOCKALIGN
, _MCISTR_int
);
692 ITEM1("level", MCI_WAVE_STATUS_LEVEL
, _MCISTR_int
);
694 case MCI_DEVTYPE_DIGITAL_VIDEO
:
695 ITEM1("audio", MCI_DGV_STATUS_AUDIO
, _MCISTR_bool
); /* FIXME? doc says MCI_ON/MCI_OFF */
696 ITEM2("audio", "alignment", MCI_DGV_STATUS_BLOCKALIGN
, _MCISTR_int
);
697 ITEM2("audio", "bitspersample", MCI_DGV_STATUS_BITSPERSAMPLE
, _MCISTR_int
);
698 /* EPP ITEM2("audio", "breaks", MCI_AVI_STATUS_AUDIO_BREAKS, _MCISTR_int); */
699 ITEM2("audio", "bytespersec", MCI_DGV_STATUS_AVGBYTESPERSEC
, _MCISTR_int
);
700 ITEM2("audio", "input", MCI_DGV_STATUS_AUDIO_INPUT
, _MCISTR_int
);
701 ITEM2("audio", "record", MCI_DGV_STATUS_AUDIO_RECORD
, _MCISTR_bool
); /* FIXME? doc says MCI_ON/MCI_OFF */
702 ITEM3("audio", "source", "number", MCI_DGV_STATUS_AUDIO_SOURCE
, _MCISTR_int
);
703 /* FIXME: ITEM2("audio", "source", MCI_DGV_STATUS_AUDIO_SOURCE, _MCISTR_dgvaudiosource); */
704 /* EPP ITEM2("audio", "samplespersec", MCI_DGV_STATUS_SAMPLESPERSECOND, _MCISTR_int); */
705 ITEM2("audio", "stream", MCI_DGV_STATUS_AUDIO_STREAM
, _MCISTR_int
);
706 ITEM1("bass", MCI_DGV_STATUS_BASS
, _MCISTR_int
);
707 ITEM1("bitsperpel", MCI_DGV_STATUS_BITSPERPEL
, _MCISTR_int
);
708 ITEM1("brightness", MCI_DGV_STATUS_BRIGHTNESS
, _MCISTR_int
);
709 ITEM1("color", MCI_DGV_STATUS_COLOR
, _MCISTR_int
);
710 ITEM1("contrast", MCI_DGV_STATUS_CONTRAST
, _MCISTR_int
);
711 /* EPP * "disk space drive" FIXME */
712 ITEM2("file", "completion", MCI_DGV_STATUS_FILE_COMPLETION
, _MCISTR_int
);
713 /* EPP ITEM2("file", "format", MCI_DGV_STATUS_FILEFORMAT, _MCISTR_???); */
714 /* EPP ITEM2("file", "mode", MCI_DGV_STATUS_FILE_MODE, _MCISTR_gdvfileformat); */
715 ITEM1("forward", MCI_DGV_STATUS_FORWARD
, _MCISTR_bool
);
716 /* EPP ITEM2("frames", "skipped", MCI_AVI_STATUS_FRAMES_SKIPPED, _MCISTR_int); */
717 ITEM1("gamma", MCI_DGV_STATUS_GAMMA
, _MCISTR_int
);
718 ITEM2("input", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
719 ITEM2("input", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
720 ITEM2("input", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
721 ITEM2("input", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
722 ITEM2("input", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
723 ITEM2("input", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
724 ITEM2("input", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
725 ITEM2("input", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_INPUT
, _MCISTR_int
);
727 ITEM2("left", "volume", MCI_DGV_STATUS_VOLUME
|MCI_DGV_STATUS_LEFT
, _MCISTR_int
);
728 ITEM2("media", "present", MCI_STATUS_MEDIA_PRESENT
, _MCISTR_bool
);
729 /* EPP ITEM2("monitor", "method", MCI_DGV_STATUS_MONITOR_METHOD, _MCISTR_monitor); */
730 /* EPP ITEM1("monitor", MCI_DGV_STATUS_MONITOR, _MCISTR_monitor2); */
731 ITEM2("nominal", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
732 ITEM2("nominal", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
733 ITEM2("nominal", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
734 ITEM2("nominal", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
735 ITEM2("nominal", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
736 ITEM2("nominal", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
737 ITEM2("nominal", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
738 ITEM2("nominal", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
739 ITEM3("nominal", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
740 ITEM4("nominal", "record", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_RECORD
|MCI_DGV_STATUS_NOMINAL
, _MCISTR_int
);
741 ITEM2("output", "bass", MCI_DGV_STATUS_BASS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
742 ITEM2("output", "brightness", MCI_DGV_STATUS_BRIGHTNESS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
743 ITEM2("output", "color", MCI_DGV_STATUS_COLOR
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
744 ITEM2("output", "contrast", MCI_DGV_STATUS_CONTRAST
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
745 ITEM2("output", "gamma", MCI_DGV_STATUS_GAMMA
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
746 ITEM2("output", "sharpness", MCI_DGV_STATUS_SHARPNESS
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
747 ITEM2("output", "tint", MCI_DGV_STATUS_TINT
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
748 ITEM2("output", "treble", MCI_DGV_STATUS_TREBLE
|MCI_DGV_STATUS_OUTPUT
, _MCISTR_int
);
749 ITEM2("palette", "handle", MCI_DGV_STATUS_HPAL
, _MCISTR_int
); /* FIXME? */
750 ITEM2("pause", "mode", MCI_DGV_STATUS_PAUSE_MODE
, _MCISTR_bool
); /* FIXME */
751 /* EPP ITEM2("play", "speed", MCI_AVI_STATUS_LAST_PLAY_SPEED, _MCISTR_int); */
752 ITEM3("record", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE
|MCI_DGV_STATUS_RECORD
, _MCISTR_int
);
753 ITEM2("reference", "frame", MCI_DGV_STATUS_FRAME_RATE
, _MCISTR_int
); /* FIXME */
754 ITEM2("reserved", "size", MCI_DGV_STATUS_SIZE
, _MCISTR_int
);
755 ITEM2("right", "volume", MCI_DGV_STATUS_VOLUME
|MCI_DGV_STATUS_RIGHT
, _MCISTR_int
);
756 ITEM2("seek", "exactly", MCI_DGV_STATUS_SEEK_EXACTLY
, _MCISTR_bool
);
757 ITEM1("sharpness", MCI_DGV_STATUS_SHARPNESS
, _MCISTR_int
);
758 /* EPP ITEM1("smpte", MCI_DGV_STATUS_SMPTE, _MCISTR_smpte); */
759 /* EPP ITEM1("speed", MCI_DGV_STATUS_SPEED, _MCISTR_speed); */
760 /* EPP ITEM3("still", "file", "format", MCI_DGV_STATUS_STILL_FILEFORMAT, _MCISTR_???); */
761 ITEM1("tint", MCI_DGV_STATUS_TINT
, _MCISTR_int
);
762 ITEM1("treble", MCI_DGV_STATUS_TREBLE
, _MCISTR_int
);
763 ITEM1("unsaved", MCI_DGV_STATUS_UNSAVED
, _MCISTR_bool
);
764 ITEM3("video", "key", "index", MCI_DGV_STATUS_KEY_INDEX
, _MCISTR_int
);
765 ITEM3("video", "key", "color", MCI_DGV_STATUS_KEY_COLOR
, _MCISTR_bool
);
766 ITEM2("video", "record", MCI_DGV_STATUS_VIDEO_RECORD
, _MCISTR_bool
); /* FIXME MCI_ON/OFF */
767 ITEM3("video", "source", "number", MCI_DGV_STATUS_VIDEO_SOURCE
, _MCISTR_int
);
768 /* EPP ITEM2("video", "source", MCI_DGV_STATUS_VIDEO_SOURCE, _MCISTR_videosrctype); */
769 ITEM2("video", "stream", MCI_DGV_STATUS_VIDEO_STREAM
, _MCISTR_int
);
770 ITEM1("video", MCI_DGV_STATUS_VIDEO
, _MCISTR_bool
); /* FIXME MCI_ON/OFF */
771 ITEM1("volume", MCI_DGV_STATUS_VOLUME
, _MCISTR_int
);
772 ITEM2("window", "handle", MCI_DGV_STATUS_HWND
, _MCISTR_int
);
773 ITEM2("window", "visible", MCI_DGV_STATUS_WINDOW_VISIBLE
, _MCISTR_bool
);
774 ITEM2("window", "minimized", MCI_DGV_STATUS_WINDOW_MINIMIZED
, _MCISTR_bool
);
775 ITEM2("window", "maximized",MCI_DGV_STATUS_WINDOW_MAXIMIZED
, _MCISTR_bool
);
778 FIXME(mci
, "unknown keyword '%s'\n", keywords
[i
]);
781 if (!pU
->statusParams
.dwItem
)
782 return MCIERR_MISSING_STRING_ARGUMENT
;
784 res
= mciSendCommandA(wDevID
, MCI_STATUS
, dwFlags
, (DWORD
)pU
);
787 _MCISTR_convreturn(type
, pU
->statusParams
.dwReturn
, lpstrReturnString
, uReturnLength
, uDevTyp
, timef
);
796 /* set specified parameters in respective MCI drivers
798 * "door open" eject media or somesuch
799 * "door close" load media
800 * "time format <timeformatname>" "ms" "milliseconds" "msf" "hmsf"
801 * "tmsf" "SMPTE 24" "SMPTE 25" "SMPTE 30"
803 * "audio [all|left|right] [on|off]" sets specified audiochannel on or off
804 * "video [on|off]" sets video on/off
806 * "formattag pcm" sets format to pcm
807 * "formattag <nr>" sets integer formattag value
808 * "any input" accept input from any known source
809 * "any output" output to any known destination
810 * "input <nr>" input from source <nr>
811 * "output <nr>" output to destination <nr>
812 * "channels <nr>" sets nr of channels
813 * "bytespersec <nr>" sets average bytes per second
814 * "samplespersec <nr>" sets average samples per second (1 sample can
816 * "alignment <nr>" sets the blockalignment to <nr>
817 * "bitspersample <nr>" sets the nr of bits per sample
819 * "master [midi|file|smpte|none]" sets the midi master device
820 * "slave [midi|file|smpte|none]" sets the midi master device
821 * "port mapper" midioutput to portmapper
822 * "port <nr>" midioutput to specified port
823 * "tempo <nr>" tempo of track (depends on timeformat/divtype)
824 * "offset <nr>" start offset?
827 MCISTR_Set(_MCISTR_PROTO_
) {
829 MCI_SET_PARMS setParams
;
830 MCI_WAVE_SET_PARMS wavesetParams
;
831 MCI_SEQ_SET_PARMS seqsetParams
;
833 union U
* pU
= xmalloc(sizeof(union U
));
836 pU
->setParams
.dwCallback
= hwndCallback
;
838 for (i
= 0; i
< nrofkeywords
; ) {
839 FLAG2("door", "open", MCI_SET_DOOR_OPEN
);
840 FLAG2("door", "closed", MCI_SET_DOOR_CLOSED
);
842 if (!STRCMP(keywords
[i
], "time") && (i
+2 < nrofkeywords
) && !STRCMP(keywords
[i
+1], "format")) {
843 dwFlags
|= MCI_SET_TIME_FORMAT
;
845 /* FIXME:is this a shortcut for milliseconds or
846 * minutes:seconds? */
847 if (!STRCMP(keywords
[i
+2], "ms"))
848 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
850 if (!STRCMP(keywords
[i
+2], "milliseconds"))
851 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
852 if (!STRCMP(keywords
[i
+2], "msf"))
853 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MSF
;
854 if (!STRCMP(keywords
[i
+2], "hms"))
855 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_HMS
;
856 if (!STRCMP(keywords
[i
+2], "frames"))
857 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_FRAMES
;
858 if (!STRCMP(keywords
[i
+2], "track"))
859 pU
->setParams
.dwTimeFormat
= MCI_VD_FORMAT_TRACK
;
860 if (!STRCMP(keywords
[i
+2], "bytes"))
861 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_BYTES
;
862 if (!STRCMP(keywords
[i
+2], "samples"))
863 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SAMPLES
;
864 if (!STRCMP(keywords
[i
+2], "tmsf"))
865 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_TMSF
;
866 if ( !STRCMP(keywords
[i
+2], "song") &&
867 (i
+3 < nrofkeywords
) &&
868 !STRCMP(keywords
[i
+3], "pointer")
870 pU
->setParams
.dwTimeFormat
= MCI_SEQ_FORMAT_SONGPTR
;
871 if (!STRCMP(keywords
[i
+2], "smpte") && (i
+3 < nrofkeywords
)) {
872 if (!STRCMP(keywords
[i
+3], "24"))
873 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_24
;
874 if (!STRCMP(keywords
[i
+3], "25"))
875 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_25
;
876 if (!STRCMP(keywords
[i
+3], "30"))
877 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30
;
878 if (!STRCMP(keywords
[i
+3], "drop") && (i
+4 < nrofkeywords
) && !STRCMP(keywords
[i
+4], "30")) {
879 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30DROP
;
888 if (!STRCMP(keywords
[i
], "audio") && (i
+1 < nrofkeywords
)) {
889 dwFlags
|= MCI_SET_AUDIO
;
890 if (!STRCMP(keywords
[i
+1], "all"))
891 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_ALL
;
892 if (!STRCMP(keywords
[i
+1], "left"))
893 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_LEFT
;
894 if (!STRCMP(keywords
[i
+1], "right"))
895 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_RIGHT
;
899 FLAG1("video", MCI_SET_VIDEO
);
900 FLAG1("on", MCI_SET_ON
);
901 FLAG1("off", MCI_SET_OFF
);
903 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
904 FLAG2("any", "input", MCI_WAVE_SET_ANYINPUT
);
905 FLAG2("any", "output", MCI_WAVE_SET_ANYOUTPUT
);
907 if ( !STRCMP(keywords
[i
], "formattag") &&
908 (i
+1 < nrofkeywords
) &&
909 !STRCMP(keywords
[i
+1], "pcm")
911 dwFlags
|= MCI_WAVE_SET_FORMATTAG
;
912 pU
->wavesetParams
.wFormatTag
= WAVE_FORMAT_PCM
;
917 /* <keyword> <integer> */
918 #define WII(str,flag,fmt,element) \
919 if (!STRCMP(keywords[i], str) && \
920 (i+1 < nrofkeywords)) { \
921 sscanf(keywords[i+1], fmt, \
922 &(pU->wavesetParams. element)); \
927 WII("formattag", MCI_WAVE_SET_FORMATTAG
, "%u", wFormatTag
);
928 WII("channels", MCI_WAVE_SET_CHANNELS
, "%u", nChannels
);
929 WII("bytespersec", MCI_WAVE_SET_AVGBYTESPERSEC
, "%lu", nAvgBytesPerSec
);
930 WII("samplespersec", MCI_WAVE_SET_SAMPLESPERSEC
, "%lu", nSamplesPerSec
);
931 WII("alignment", MCI_WAVE_SET_BLOCKALIGN
, "%u", nBlockAlign
);
932 WII("bitspersample", MCI_WAVE_SET_BITSPERSAMPLE
, "%u", wBitsPerSample
);
933 WII("input", MCI_WAVE_INPUT
, "%u", wInput
);
934 WII("output", MCI_WAVE_OUTPUT
, "%u", wOutput
);
937 case MCI_DEVTYPE_SEQUENCER
:
938 if (!STRCMP(keywords
[i
], "master") && (i
+1 < nrofkeywords
)) {
939 dwFlags
|= MCI_SEQ_SET_MASTER
;
940 if (!STRCMP(keywords
[i
+1], "midi"))
941 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
942 if (!STRCMP(keywords
[i
+1], "file"))
943 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
944 if (!STRCMP(keywords
[i
+1], "smpte"))
945 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
946 if (!STRCMP(keywords
[i
+1], "none"))
947 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
951 if (!STRCMP(keywords
[i
], "slave") && (i
+1 < nrofkeywords
)) {
952 dwFlags
|= MCI_SEQ_SET_SLAVE
;
953 if (!STRCMP(keywords
[i
+1], "midi"))
954 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
955 if (!STRCMP(keywords
[i
+1], "file"))
956 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
957 if (!STRCMP(keywords
[i
+1], "smpte"))
958 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
959 if (!STRCMP(keywords
[i
+1], "none"))
960 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
964 if ( !STRCMP(keywords
[i
], "port") &&
965 (i
+1 < nrofkeywords
) &&
966 !STRCMP(keywords
[i
+1], "mapper")
968 pU
->seqsetParams
.dwPort
=-1;/* FIXME:not sure*/
969 dwFlags
|= MCI_SEQ_SET_PORT
;
973 #define SII(str,flag,element) \
974 if (!STRCMP(keywords[i], str) && \
975 (i+1 < nrofkeywords)) { \
976 sscanf(keywords[i+1], "%ld", \
977 &(pU->seqsetParams.element));\
982 SII("tempo", MCI_SEQ_SET_TEMPO
, dwTempo
);
983 SII("port", MCI_SEQ_SET_PORT
, dwPort
);
984 SII("offset", MCI_SEQ_SET_PORT
, dwOffset
);
990 return MCIERR_MISSING_STRING_ARGUMENT
;
991 res
= mciSendCommandA(wDevID
, MCI_SET
, dwFlags
, (DWORD
)pU
);
998 * "off" disable break
999 * "on <keyid>" enable break on key with keyid
1000 * (I strongly suspect, that there is another parameter:
1002 * but I don't see it mentioned in my documentation.
1006 MCISTR_Break(_MCISTR_PROTO_
)
1008 LPMCI_BREAK_PARMS breakParams
= xmalloc(sizeof(MCI_BREAK_PARMS
));
1011 if (!breakParams
) return 0;
1013 breakParams
->dwCallback
= hwndCallback
;
1014 /*breakParams.hwndBreak ? */
1015 for (i
= 0; i
< nrofkeywords
; i
++) {
1016 FLAG1("off", MCI_BREAK_OFF
);
1017 if (!STRCMP(keywords
[i
], "on") && (nrofkeywords
> i
+1)) {
1018 dwFlags
&= ~MCI_BREAK_OFF
;
1019 dwFlags
|= MCI_BREAK_KEY
;
1020 sscanf(keywords
[i
+1], "%d", &(breakParams
->nVirtKey
));
1025 res
= mciSendCommandA(wDevID
, MCI_BREAK
, dwFlags
, (DWORD
)breakParams
);
1030 #define ITEM1(str, item, xtype) \
1031 if (!STRCMP(keywords[i], str)) { \
1032 gdcParams->dwItem = item; \
1037 #define ITEM2(str1, str2, item, xtype) \
1038 if ( !STRCMP(keywords[i], str1) && \
1039 (i+1 < nrofkeywords) && \
1040 !STRCMP(keywords[i+1], str2)) { \
1041 gdcParams->dwItem = item; \
1046 #define ITEM3(str1, str2, str3, item, xtype) \
1047 if ( !STRCMP(keywords[i], str1) && \
1048 (i+2 < nrofkeywords) && \
1049 !STRCMP(keywords[i+1], str2) && \
1050 !STRCMP(keywords[i+2], str3)) { \
1051 gdcParams->dwItem = item; \
1057 /* get device capabilities of MCI drivers
1060 * "device type" returns device name as string
1061 * "has audio" returns bool
1062 * "has video" returns bool
1063 * "uses files" returns bool
1064 * "compound device" returns bool
1065 * "can record" returns bool
1066 * "can play" returns bool
1067 * "can eject" returns bool
1068 * "can save" returns bool
1070 * "palettes" returns nr of available palette entries
1071 * "windows" returns nr of available windows
1072 * "can reverse" returns bool
1073 * "can stretch" returns bool
1074 * "slow play rate" returns the slow playrate
1075 * "fast play rate" returns the fast playrate
1076 * "normal play rate" returns the normal playrate
1078 * "can freeze" returns bool
1079 * "can lock" returns bool
1080 * "can reverse" returns bool
1081 * "can stretch" returns bool
1082 * "can stretch input" returns bool
1083 * "can test" returns bool
1084 * "has still" returns bool
1085 * "maximum play rate" returns the maximum play rate, in fps
1086 * "minimum play rate" returns the minimum play rate, in fps
1087 * "uses files" returns bool
1088 * "uses palettes" returns bool
1089 * "windows" returns nr of available windows
1091 * "windows" returns nr of available windows
1092 * "can stretch" returns bool
1093 * "can freeze" returns bool
1095 * "cav" assume CAV discs (default if no disk inserted)
1096 * "clv" assume CLV discs
1097 * "can reverse" returns bool
1098 * "slow play rate" returns the slow playrate
1099 * "fast play rate" returns the fast playrate
1100 * "normal play rate" returns the normal playrate
1102 * "inputs" returns nr of inputdevices
1103 * "outputs" returns nr of outputdevices
1106 MCISTR_Capability(_MCISTR_PROTO_
) {
1107 MCI_GETDEVCAPS_PARMS
*gdcParams
= xmalloc(sizeof(MCI_GETDEVCAPS_PARMS
));
1110 gdcParams
->dwCallback
= hwndCallback
;
1112 return MCIERR_MISSING_STRING_ARGUMENT
;
1113 /* well , thats default */
1114 dwFlags
|= MCI_GETDEVCAPS_ITEM
;
1115 gdcParams
->dwItem
= 0;
1117 for (i
= 0; i
< nrofkeywords
; i
++) {
1118 ITEM2("device", "type", MCI_GETDEVCAPS_DEVICE_TYPE
, _MCISTR_devtype
);
1119 ITEM2("has", "audio", MCI_GETDEVCAPS_HAS_AUDIO
, _MCISTR_bool
);
1120 ITEM2("has", "video", MCI_GETDEVCAPS_HAS_VIDEO
, _MCISTR_bool
);
1121 ITEM2("uses", "files", MCI_GETDEVCAPS_USES_FILES
, _MCISTR_bool
);
1122 ITEM2("compound", "device", MCI_GETDEVCAPS_COMPOUND_DEVICE
, _MCISTR_bool
);
1123 ITEM2("can", "record", MCI_GETDEVCAPS_CAN_RECORD
, _MCISTR_bool
);
1124 ITEM2("can", "play", MCI_GETDEVCAPS_CAN_PLAY
, _MCISTR_bool
);
1125 ITEM2("can", "eject", MCI_GETDEVCAPS_CAN_EJECT
, _MCISTR_bool
);
1126 ITEM2("can", "save", MCI_GETDEVCAPS_CAN_SAVE
, _MCISTR_bool
);
1128 case MCI_DEVTYPE_ANIMATION
:
1129 ITEM1("palettes", MCI_ANIM_GETDEVCAPS_PALETTES
, _MCISTR_int
);
1130 ITEM1("windows", MCI_ANIM_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1131 ITEM2("can", "reverse", MCI_ANIM_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1132 ITEM2("can", "stretch", MCI_ANIM_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1133 ITEM3("slow", "play", "rate", MCI_ANIM_GETDEVCAPS_SLOW_RATE
, _MCISTR_int
);
1134 ITEM3("fast", "play", "rate", MCI_ANIM_GETDEVCAPS_FAST_RATE
, _MCISTR_int
);
1135 ITEM3("normal", "play", "rate", MCI_ANIM_GETDEVCAPS_NORMAL_RATE
, _MCISTR_int
);
1137 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1138 ITEM2("can", "freeze", MCI_DGV_GETDEVCAPS_CAN_FREEZE
, _MCISTR_bool
);
1139 ITEM2("can", "lock", MCI_DGV_GETDEVCAPS_CAN_LOCK
, _MCISTR_bool
);
1140 ITEM2("can", "reverse", MCI_DGV_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1141 ITEM3("can", "stretch", "input", MCI_DGV_GETDEVCAPS_CAN_STR_IN
, _MCISTR_bool
);
1142 ITEM2("can", "stretch", MCI_DGV_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1143 ITEM2("can", "test", MCI_DGV_GETDEVCAPS_CAN_TEST
, _MCISTR_bool
);
1144 ITEM2("has", "still", MCI_DGV_GETDEVCAPS_HAS_STILL
, _MCISTR_bool
);
1145 ITEM3("maximum", "play", "rate", MCI_DGV_GETDEVCAPS_MAXIMUM_RATE
, _MCISTR_int
);
1146 ITEM3("minimum", "play", "rate", MCI_DGV_GETDEVCAPS_MINIMUM_RATE
, _MCISTR_int
);
1147 ITEM2("uses", "files", MCI_GETDEVCAPS_USES_FILES
, _MCISTR_bool
);
1148 ITEM2("uses", "palettes", MCI_DGV_GETDEVCAPS_PALETTES
, _MCISTR_bool
);
1149 ITEM1("windows", MCI_DGV_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1151 case MCI_DEVTYPE_OVERLAY
:
1152 ITEM1("windows", MCI_OVLY_GETDEVCAPS_MAX_WINDOWS
, _MCISTR_int
);
1153 ITEM2("can", "freeze", MCI_OVLY_GETDEVCAPS_CAN_FREEZE
, _MCISTR_bool
);
1154 ITEM2("can", "stretch", MCI_OVLY_GETDEVCAPS_CAN_STRETCH
, _MCISTR_bool
);
1156 case MCI_DEVTYPE_VIDEODISC
:
1157 FLAG1("cav", MCI_VD_GETDEVCAPS_CAV
);
1158 FLAG1("clv", MCI_VD_GETDEVCAPS_CLV
);
1159 ITEM2("can", "reverse", MCI_VD_GETDEVCAPS_CAN_REVERSE
, _MCISTR_bool
);
1160 ITEM3("slow", "play", "rate", MCI_VD_GETDEVCAPS_SLOW_RATE
, _MCISTR_int
);
1161 ITEM3("fast", "play", "rate", MCI_VD_GETDEVCAPS_FAST_RATE
, _MCISTR_int
);
1162 ITEM3("normal", "play", "rate", MCI_VD_GETDEVCAPS_NORMAL_RATE
, _MCISTR_int
);
1164 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
1165 ITEM1("inputs", MCI_WAVE_GETDEVCAPS_INPUTS
, _MCISTR_int
);
1166 ITEM1("outputs", MCI_WAVE_GETDEVCAPS_OUTPUTS
, _MCISTR_int
);
1170 res
= mciSendCommandA(wDevID
, MCI_GETDEVCAPS
, dwFlags
, (DWORD
)gdcParams
);
1172 /* no timeformat needed */
1174 _MCISTR_convreturn(type
, gdcParams
->dwReturn
, lpstrReturnString
,
1175 uReturnLength
, uDevTyp
, 0);
1182 /* resumes operation of device. no arguments, no return values */
1184 MCISTR_Resume(_MCISTR_PROTO_
)
1186 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1189 genParams
->dwCallback
= hwndCallback
;
1190 res
= mciSendCommandA(wDevID
, MCI_RESUME
, dwFlags
, (DWORD
)genParams
);
1195 /* pauses operation of device. no arguments, no return values */
1197 MCISTR_Pause(_MCISTR_PROTO_
)
1199 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1202 genParams
->dwCallback
= hwndCallback
;
1203 res
= mciSendCommandA(wDevID
, MCI_PAUSE
, dwFlags
, (DWORD
)genParams
);
1208 /* stops operation of device. no arguments, no return values */
1210 MCISTR_Stop(_MCISTR_PROTO_
)
1212 MCI_GENERIC_PARMS
* genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1215 genParams
->dwCallback
= hwndCallback
;
1216 res
= mciSendCommandA(wDevID
, MCI_STOP
, dwFlags
, (DWORD
)genParams
);
1221 /* starts recording.
1223 * "overwrite" overwrite existing things
1224 * "insert" insert at current position
1225 * "to <time>" record up to <time> (specified in timeformat)
1226 * "from <time>" record from <time> (specified in timeformat)
1229 MCISTR_Record(_MCISTR_PROTO_
) {
1230 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1232 MCI_RECORD_PARMS
*recordParams
= xmalloc(sizeof(MCI_RECORD_PARMS
));
1234 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1235 if (res
) return res
;
1238 case MCI_FORMAT_MILLISECONDS
:
1239 case MCI_FORMAT_FRAMES
:
1240 case MCI_FORMAT_BYTES
:
1241 case MCI_FORMAT_SAMPLES
:
1245 case MCI_FORMAT_HMS
:
1246 case MCI_FORMAT_MSF
:
1247 parsestr
="%d:%d:%d";
1250 case MCI_FORMAT_TMSF
:
1251 parsestr
="%d:%d:%d:%d";
1254 default:FIXME(mci
, "unknown timeformat %d, please report.\n", timef
);
1259 recordParams
->dwCallback
= hwndCallback
;
1260 for (i
= 0; i
< nrofkeywords
; ) {
1261 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1263 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1264 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1265 /* add up all integers we got, if we have more
1266 * shift them. (Well I should use the macros in
1267 * mmsystem.h, right).
1269 recordParams
->dwTo
= 0;
1270 for (k
= 0; k
< j
; k
++)
1271 recordParams
->dwTo
+= a
[k
] << (8*(nrargs
-k
));
1275 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1276 dwFlags
|= MCI_FROM
;
1277 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1278 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1280 recordParams
->dwFrom
= 0;
1281 for (k
= 0; k
< j
; k
++)
1282 recordParams
->dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1286 FLAG1("insert", MCI_RECORD_INSERT
);
1287 FLAG1("overwrite", MCI_RECORD_OVERWRITE
);
1290 res
= mciSendCommandA(wDevID
, MCI_RECORD
, dwFlags
, (DWORD
)recordParams
);
1297 * "to <time>" play up to <time> (specified in set timeformat)
1298 * "from <time>" play from <time> (specified in set timeformat)
1302 * "scan" play as fast as possible (with audio disabled perhaps)
1303 * "reverse" play reverse
1304 * "speed <fps>" play with specified frames per second
1308 * "scan" play as fast as possible (with audio disabled perhaps)
1309 * "reverse" play reverse
1310 * "speed <fps>" play with specified frames per second
1318 MCISTR_Play(_MCISTR_PROTO_
) {
1319 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1322 MCI_PLAY_PARMS playParams
;
1323 MCI_VD_PLAY_PARMS vdplayParams
;
1324 MCI_ANIM_PLAY_PARMS animplayParams
;
1325 MCI_DGV_PLAY_PARMS dgvplayParams
;
1327 union U
*pU
= xmalloc(sizeof(union U
));
1329 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1330 if (res
) return res
;
1332 case MCI_FORMAT_MILLISECONDS
:
1333 case MCI_FORMAT_FRAMES
:
1334 case MCI_FORMAT_BYTES
:
1335 case MCI_FORMAT_SAMPLES
:
1339 case MCI_FORMAT_HMS
:
1340 case MCI_FORMAT_MSF
:
1341 parsestr
="%d:%d:%d";
1344 case MCI_FORMAT_TMSF
:
1345 parsestr
="%d:%d:%d:%d";
1348 default:FIXME(mci
, "unknown timeformat %d, please report.\n", timef
);
1353 pU
->playParams
.dwCallback
= hwndCallback
;
1354 for (i
= 0; i
< nrofkeywords
; ) {
1355 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1357 a
[0]=a
[1]=a
[2]=a
[3]=0;
1358 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1359 /* add up all integers we got, if we have more
1360 * shift them. (Well I should use the macros in
1361 * mmsystem.h, right).
1363 pU
->playParams
.dwTo
=0;
1364 for (k
= 0; k
< j
; k
++)
1365 pU
->playParams
.dwTo
+= a
[k
] << (8*(nrargs
-k
));
1369 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1370 dwFlags
|= MCI_FROM
;
1371 a
[0]=a
[1]=a
[2]=a
[3]=0;
1372 j
=sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1374 pU
->playParams
.dwFrom
=0;
1375 for (k
= 0; k
< j
; k
++)
1376 pU
->playParams
.dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1381 case MCI_DEVTYPE_VIDEODISC
:
1382 FLAG1("slow", MCI_VD_PLAY_SLOW
);
1383 FLAG1("fast", MCI_VD_PLAY_FAST
);
1384 FLAG1("scan", MCI_VD_PLAY_SCAN
);
1385 FLAG1("reverse", MCI_VD_PLAY_REVERSE
);
1386 if (!STRCMP(keywords
[i
], "speed") && (i
+1 < nrofkeywords
)) {
1387 dwFlags
|= MCI_VD_PLAY_SPEED
;
1388 sscanf(keywords
[i
+1], "%ld", &(pU
->vdplayParams
.dwSpeed
));
1393 case MCI_DEVTYPE_ANIMATION
:
1394 FLAG1("slow", MCI_ANIM_PLAY_SLOW
);
1395 FLAG1("fast", MCI_ANIM_PLAY_FAST
);
1396 FLAG1("scan", MCI_ANIM_PLAY_SCAN
);
1397 FLAG1("reverse", MCI_ANIM_PLAY_REVERSE
);
1398 if (!STRCMP(keywords
[i
], "speed") && (i
+1 < nrofkeywords
)) {
1399 dwFlags
|= MCI_ANIM_PLAY_SPEED
;
1400 sscanf(keywords
[i
+1], "%ld", &(pU
->animplayParams
.dwSpeed
));
1405 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1406 /* EPP FLAG1("fullscreen", MCI_MCIAVI_PLAY_FULLSCREEN); */
1407 FLAG1("repeat", MCI_DGV_PLAY_REPEAT
);
1408 FLAG1("reverse", MCI_DGV_PLAY_REVERSE
);
1409 /* EPP FLAG1("window", MCI_MCIAVI_PLAY_WINDOW); */
1414 res
= mciSendCommandA(wDevID
, MCI_PLAY
, dwFlags
, (DWORD
)pU
);
1419 /* seek to a specified position
1421 * "to start" seek to start of medium
1422 * "to end" seek to end of medium
1423 * "to <time>" seek to <time> specified in current timeformat
1426 MCISTR_Seek(_MCISTR_PROTO_
) {
1427 int i
, res
, timef
, nrargs
, j
, k
, a
[4];
1429 MCI_SEEK_PARMS
*seekParams
= xmalloc(sizeof(MCI_SEEK_PARMS
));
1431 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1432 if (res
) return res
;
1434 case MCI_FORMAT_MILLISECONDS
:
1435 case MCI_FORMAT_FRAMES
:
1436 case MCI_FORMAT_BYTES
:
1437 case MCI_FORMAT_SAMPLES
:
1441 case MCI_FORMAT_HMS
:
1442 case MCI_FORMAT_MSF
:
1443 parsestr
="%d:%d:%d";
1446 case MCI_FORMAT_TMSF
:
1447 parsestr
="%d:%d:%d:%d";
1451 FIXME(mci
, "unknown timeformat %d, please report.\n", timef
);
1456 seekParams
->dwCallback
= hwndCallback
;
1457 for (i
= 0; i
< nrofkeywords
; ) {
1458 if (!STRCMP(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1459 if (!STRCMP(keywords
[i
+1], "start")) {
1460 dwFlags
|= MCI_SEEK_TO_START
;
1461 seekParams
->dwTo
= 0;
1465 if (!STRCMP(keywords
[i
+1], "end")) {
1466 dwFlags
|= MCI_SEEK_TO_END
;
1467 seekParams
->dwTo
= 0;
1473 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1474 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1475 seekParams
->dwTo
= 0;
1476 for (k
= 0; k
< j
; k
++)
1477 seekParams
->dwTo
+= a
[k
] << (8*(nrargs
-k
));
1481 case MCI_DEVTYPE_VIDEODISC
:
1482 FLAG1("reverse", MCI_VD_SEEK_REVERSE
);
1487 res
= mciSendCommandA(wDevID
, MCI_SEEK
, dwFlags
, (DWORD
)seekParams
);
1492 /* close media/driver */
1494 MCISTR_Close(_MCISTR_PROTO_
)
1496 MCI_GENERIC_PARMS
* closeParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1499 closeParams
->dwCallback
= hwndCallback
;
1500 res
= mciSendCommandA(wDevID
, MCI_CLOSE
, dwFlags
, (DWORD
)closeParams
);
1505 /* return information.
1507 * "product" return product name (human readable)
1508 * "file" return filename
1510 * "text" returns text?
1512 * "text" returns text?
1525 MCISTR_Info(_MCISTR_PROTO_
)
1528 MCI_INFO_PARMSA infoParams
;
1529 MCI_DGV_INFO_PARMSA dgvinfoParams
;
1531 union U
* pU
= xmalloc(sizeof(union U
));
1536 for (i
= 0; i
< nrofkeywords
; i
++) {
1537 FLAG1("product", MCI_INFO_PRODUCT
);
1538 FLAG1("file", MCI_INFO_FILE
);
1540 case MCI_DEVTYPE_ANIMATION
:
1541 FLAG2("window", "text", MCI_ANIM_INFO_TEXT
);
1543 case MCI_DEVTYPE_OVERLAY
:
1544 FLAG2("window", "text", MCI_OVLY_INFO_TEXT
);
1546 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1547 #define MI1(str, flag) \
1548 if (!STRCMP(keywords[i], str)) { \
1549 dwFlags |= MCI_DGV_INFO_ITEM; \
1550 pU->dgvinfoParams.dwItem |= flag; \
1554 #define MI2(str1, str2, flag) \
1555 if (!STRCMP(keywords[i], str1) && \
1556 (i+1 < nrofkeywords) && \
1557 !STRCMP(keywords[i+1], str2)) { \
1558 dwFlags |= MCI_DGV_INFO_ITEM; \
1559 pU->dgvinfoParams.dwItem |= flag; \
1563 MI2("audio", "algorithm", MCI_DGV_INFO_AUDIO_ALG
);
1564 MI2("audio", "quality", MCI_DGV_INFO_AUDIO_QUALITY
);
1565 MI2("still", "algorithm", MCI_DGV_INFO_STILL_ALG
);
1566 MI2("still", "quality", MCI_DGV_INFO_STILL_QUALITY
);
1567 MI1("usage", MCI_DGV_INFO_USAGE
);
1568 MI1("version", MCI_INFO_VERSION
);
1569 MI2("video", "algorithm", MCI_DGV_INFO_VIDEO_ALG
);
1570 MI2("video", "quality", MCI_DGV_INFO_VIDEO_QUALITY
);
1571 MI2("window", "text", MCI_DGV_INFO_TEXT
);
1576 if (dwFlags
== sflags
)
1577 return MCIERR_MISSING_STRING_ARGUMENT
;
1578 pU
->infoParams
.dwCallback
= hwndCallback
;
1580 /* MCI driver will fill in lpstrReturn, dwRetSize.
1581 * FIXME: I don't know if this is correct behaviour
1583 res
= mciSendCommandA(wDevID
, MCI_INFO
, dwFlags
, (DWORD
)pU
);
1585 _MCI_STR(pU
->infoParams
.lpstrReturn
);
1590 /* query MCI driver itself for information
1592 * "installname" return install name of <device> (system.ini)
1593 * "quantity" return nr of installed drivers
1594 * "open" open drivers only (additional flag)
1595 * "name <nr>" return nr of devices with <devicetyp>
1596 * "name all" return nr of all devices
1600 MCISTR_Sysinfo(_MCISTR_PROTO_
) {
1601 MCI_SYSINFO_PARMSA sysinfoParams
;
1604 sysinfoParams
.lpstrReturn
= lpstrReturnString
;
1605 sysinfoParams
.dwRetSize
= uReturnLength
;
1606 sysinfoParams
.wDeviceType
= uDevTyp
;
1607 sysinfoParams
.dwCallback
= hwndCallback
;
1609 for (i
= 0; i
< nrofkeywords
; i
++) {
1610 FLAG1("installname", MCI_SYSINFO_INSTALLNAME
);
1611 FLAG1("quantity", MCI_SYSINFO_INSTALLNAME
);
1612 FLAG1("open", MCI_SYSINFO_OPEN
);
1613 if (!strcmp(keywords
[i
], "name") && (i
+1 < nrofkeywords
)) {
1614 sscanf(keywords
[i
+1], "%ld", &(sysinfoParams
.dwNumber
));
1615 dwFlags
|= MCI_SYSINFO_NAME
;
1619 res
= mciSendCommandA(0, MCI_SYSINFO
, dwFlags
, (DWORD
)&sysinfoParams
);
1621 if (dwFlags
& MCI_SYSINFO_QUANTITY
) {
1624 sprintf(buf
, "%ld", *(long*)lpstrReturnString
);
1627 /* no need to copy anything back, mciSysInfo did it for us */
1632 * Argument: "<filename>"
1633 * Overlay: "at <left> <top> <right> <bottom>" additional
1636 MCISTR_Load(_MCISTR_PROTO_
) {
1638 MCI_LOAD_PARMSA loadParams
;
1639 MCI_OVLY_LOAD_PARMSA ovlyloadParams
;
1641 union U
*pU
= xmalloc(sizeof(union U
));
1642 int i
, len
= 0, res
;
1645 for (i
= 0; i
< nrofkeywords
; ) {
1647 case MCI_DEVTYPE_OVERLAY
:
1648 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1649 dwFlags
|= MCI_OVLY_RECT
;
1650 sscanf(keywords
[i
+1], "%d", &(pU
->ovlyloadParams
.rc
.left
));
1651 sscanf(keywords
[i
+2], "%d", &(pU
->ovlyloadParams
.rc
.top
));
1652 sscanf(keywords
[i
+3], "%d", &(pU
->ovlyloadParams
.rc
.right
));
1653 sscanf(keywords
[i
+4], "%d", &(pU
->ovlyloadParams
.rc
.bottom
));
1654 memcpy(keywords
+i
, keywords
+(i
+5), nrofkeywords
-(i
+5));
1659 len
+= strlen(keywords
[i
])+1;
1662 s
=(char*)xmalloc(len
);
1664 while (i
< nrofkeywords
) {
1665 strcat(s
, keywords
[i
]);
1667 if (i
< nrofkeywords
) strcat(s
, " ");
1669 pU
->loadParams
.lpfilename
= s
;
1670 pU
->loadParams
.dwCallback
= hwndCallback
;
1671 dwFlags
|= MCI_LOAD_FILE
;
1672 res
= mciSendCommandA(wDevID
, MCI_LOAD
, dwFlags
, (DWORD
)pU
);
1679 * Argument: "<filename>"
1680 * Overlay: "at <left> <top> <right> <bottom>" additional
1683 MCISTR_Save(_MCISTR_PROTO_
) {
1685 MCI_SAVE_PARMS saveParams
;
1686 MCI_OVLY_SAVE_PARMSA ovlysaveParams
;
1688 union U
* pU
= xmalloc(sizeof(union U
));
1689 int i
, len
= 0, res
;
1692 for (i
= 0; i
< nrofkeywords
; ) {
1694 case MCI_DEVTYPE_OVERLAY
:
1695 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1696 dwFlags
|= MCI_OVLY_RECT
;
1697 sscanf(keywords
[i
+1], "%d", &(pU
->ovlysaveParams
.rc
.left
));
1698 sscanf(keywords
[i
+2], "%d", &(pU
->ovlysaveParams
.rc
.top
));
1699 sscanf(keywords
[i
+3], "%d", &(pU
->ovlysaveParams
.rc
.right
));
1700 sscanf(keywords
[i
+4], "%d", &(pU
->ovlysaveParams
.rc
.bottom
));
1701 memcpy(keywords
+i
, keywords
+(i
+5), nrofkeywords
-(i
+5));
1706 len
+= strlen(keywords
[i
])+1;
1709 s
= (char*)xmalloc(len
);
1711 while (i
< nrofkeywords
) {
1712 strcat(s
, keywords
[i
]);
1714 if (i
< nrofkeywords
) strcat(s
, " ");
1716 pU
->saveParams
.lpfilename
= s
;
1717 pU
->saveParams
.dwCallback
= hwndCallback
;
1718 dwFlags
|= MCI_LOAD_FILE
;
1719 res
= mciSendCommandA(wDevID
, MCI_SAVE
, dwFlags
, (DWORD
)pU
);
1725 /* prepare device for input/output
1726 * (only applyable to waveform audio)
1729 MCISTR_Cue(_MCISTR_PROTO_
) {
1730 MCI_GENERIC_PARMS
*cueParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1733 for (i
= 0; i
< nrofkeywords
; i
++) {
1735 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
1736 FLAG1("input", MCI_WAVE_INPUT
);
1737 FLAG1("output", MCI_WAVE_OUTPUT
);
1742 cueParams
->dwCallback
= hwndCallback
;
1744 res
= mciSendCommandA(wDevID
, MCI_CUE
, dwFlags
, (DWORD
)cueParams
);
1749 /* delete information */
1751 MCISTR_Delete(_MCISTR_PROTO_
) {
1752 int timef
, nrargs
, i
, j
, k
, a
[4], res
;
1754 MCI_WAVE_DELETE_PARMS
*deleteParams
= xmalloc(sizeof(MCI_WAVE_DELETE_PARMS
));
1756 /* only implemented for waveform audio */
1757 if (uDevTyp
!= MCI_DEVTYPE_WAVEFORM_AUDIO
)
1758 return MCIERR_UNSUPPORTED_FUNCTION
; /* well it fits */
1759 res
= _MCISTR_determine_timeformat(dev
, wDevID
, uDevTyp
, &timef
);
1760 if (res
) return res
;
1762 case MCI_FORMAT_MILLISECONDS
:
1763 case MCI_FORMAT_FRAMES
:
1764 case MCI_FORMAT_BYTES
:
1765 case MCI_FORMAT_SAMPLES
:
1769 case MCI_FORMAT_HMS
:
1770 case MCI_FORMAT_MSF
:
1771 parsestr
="%d:%d:%d";
1774 case MCI_FORMAT_TMSF
:
1775 parsestr
="%d:%d:%d:%d";
1778 default:FIXME(mci
, "unknown timeformat %d, please report.\n", timef
);
1783 for (i
= 0; i
< nrofkeywords
; ) {
1784 if (!strcmp(keywords
[i
], "to") && (i
+1 < nrofkeywords
)) {
1786 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1787 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1788 /* add up all integers we got, if we have more
1789 * shift them. (Well I should use the macros in
1790 * mmsystem.h, right).
1792 deleteParams
->dwTo
= 0;
1793 for (k
= 0;k
< j
;k
++)
1794 deleteParams
->dwTo
+= a
[k
]<<(8*(nrargs
-k
));
1798 if (!strcmp(keywords
[i
], "from") && (i
+1 < nrofkeywords
)) {
1799 dwFlags
|= MCI_FROM
;
1800 a
[0] = a
[1] = a
[2] = a
[3] = 0;
1801 j
= sscanf(keywords
[i
+1], parsestr
, &a
[0], &a
[1], &a
[2], &a
[3]);
1803 deleteParams
->dwFrom
= 0;
1804 for (k
= 0; k
< j
; k
++)
1805 deleteParams
->dwFrom
+= a
[k
]<<(8*(nrargs
-k
));
1811 deleteParams
->dwCallback
= hwndCallback
;
1812 res
= mciSendCommandA(wDevID
, MCI_DELETE
, dwFlags
, (DWORD
)deleteParams
);
1817 /* send command to device. only applies to videodisc */
1819 MCISTR_Escape(_MCISTR_PROTO_
)
1821 LPMCI_VD_ESCAPE_PARMSA escapeParams
= xmalloc(sizeof(MCI_VD_ESCAPE_PARMSA
));
1822 int i
, len
= 0, res
;
1825 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
1826 return MCIERR_UNSUPPORTED_FUNCTION
;
1828 for (i
= 0; i
< nrofkeywords
; i
++) {
1829 len
+= strlen(keywords
[i
]) + 1;
1831 s
= (char*)malloc(len
);
1833 for (i
= 0; i
< nrofkeywords
; ) {
1834 strcat(s
, keywords
[i
]);
1836 if (i
< nrofkeywords
) strcat(s
, " ");
1838 escapeParams
->lpstrCommand
= s
;
1839 escapeParams
->dwCallback
= hwndCallback
;
1840 dwFlags
|= MCI_VD_ESCAPE_STRING
;
1841 res
= mciSendCommandA(wDevID
, MCI_ESCAPE
, dwFlags
, (DWORD
)escapeParams
);
1847 /* unfreeze [part of] the overlayed video
1848 * only applyable to Overlay devices
1851 MCISTR_Unfreeze(_MCISTR_PROTO_
)
1853 LPMCI_OVLY_RECT_PARMS unfreezeParams
= xmalloc(sizeof(MCI_OVLY_RECT_PARMS
));
1856 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1857 return MCIERR_UNSUPPORTED_FUNCTION
;
1858 for (i
= 0; i
< nrofkeywords
; ) {
1859 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1860 sscanf(keywords
[i
+1], "%d", &(unfreezeParams
->rc
.left
));
1861 sscanf(keywords
[i
+2], "%d", &(unfreezeParams
->rc
.top
));
1862 sscanf(keywords
[i
+3], "%d", &(unfreezeParams
->rc
.right
));
1863 sscanf(keywords
[i
+4], "%d", &(unfreezeParams
->rc
.bottom
));
1864 dwFlags
|= MCI_OVLY_RECT
;
1870 unfreezeParams
->dwCallback
= hwndCallback
;
1871 res
= mciSendCommandA(wDevID
, MCI_UNFREEZE
, dwFlags
, (DWORD
)unfreezeParams
);
1872 free(unfreezeParams
);
1875 /* freeze [part of] the overlayed video
1876 * only applyable to Overlay devices
1879 MCISTR_Freeze(_MCISTR_PROTO_
)
1881 LPMCI_OVLY_RECT_PARMS freezeParams
= xmalloc(sizeof(MCI_OVLY_RECT_PARMS
));
1884 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1885 return MCIERR_UNSUPPORTED_FUNCTION
;
1886 for (i
= 0; i
< nrofkeywords
; ) {
1887 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1888 sscanf(keywords
[i
+1], "%d", &(freezeParams
->rc
.left
));
1889 sscanf(keywords
[i
+2], "%d", &(freezeParams
->rc
.top
));
1890 sscanf(keywords
[i
+3], "%d", &(freezeParams
->rc
.right
));
1891 sscanf(keywords
[i
+4], "%d", &(freezeParams
->rc
.bottom
));
1892 dwFlags
|= MCI_OVLY_RECT
;
1898 freezeParams
->dwCallback
= hwndCallback
;
1899 res
= mciSendCommandA(wDevID
, MCI_FREEZE
, dwFlags
, (DWORD
)freezeParams
);
1904 /* copy parts of image to somewhere else
1905 * "source [at <left> <top> <right> <bottom>]" source is framebuffer [or rect]
1906 * "destination [at <left> <top> <right> <bottom>]" destination is framebuffer [or rect]
1908 * "frame [at <left> <top> <right> <bottom>]" frame is framebuffer [or rect]
1909 * where the video input is placed
1910 * "video [at <left> <top> <right> <bottom>]" video is whole video [or rect]
1911 * (defining part of input to
1913 * FIXME: This whole junk is passing multiple rectangles.
1914 * I don't know how to do that with the present interface.
1915 * (Means code below is broken)
1918 MCISTR_Put(_MCISTR_PROTO_
) {
1920 MCI_OVLY_RECT_PARMS ovlyputParams
;
1921 MCI_ANIM_RECT_PARMS animputParams
;
1922 MCI_DGV_RECT_PARMS dgvputParams
;
1924 union U
* pU
= xmalloc(sizeof(union U
));
1927 for (i
= 0; i
< nrofkeywords
; ) {
1929 case MCI_DEVTYPE_ANIMATION
:
1930 FLAG1("source", MCI_ANIM_PUT_SOURCE
);
1931 FLAG1("destination", MCI_ANIM_PUT_DESTINATION
);
1932 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1933 sscanf(keywords
[i
+1], "%d", &(pU
->animputParams
.rc
.left
));
1934 sscanf(keywords
[i
+2], "%d", &(pU
->animputParams
.rc
.top
));
1935 sscanf(keywords
[i
+3], "%d", &(pU
->animputParams
.rc
.right
));
1936 sscanf(keywords
[i
+4], "%d", &(pU
->animputParams
.rc
.bottom
));
1937 dwFlags
|= MCI_ANIM_RECT
;
1942 case MCI_DEVTYPE_OVERLAY
:
1943 FLAG1("source", MCI_OVLY_PUT_SOURCE
);
1944 FLAG1("destination", MCI_OVLY_PUT_DESTINATION
);
1945 FLAG1("video", MCI_OVLY_PUT_VIDEO
);
1946 FLAG1("frame", MCI_OVLY_PUT_FRAME
);
1947 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1948 sscanf(keywords
[i
+1], "%d", &(pU
->ovlyputParams
.rc
.left
));
1949 sscanf(keywords
[i
+2], "%d", &(pU
->ovlyputParams
.rc
.top
));
1950 sscanf(keywords
[i
+3], "%d", &(pU
->ovlyputParams
.rc
.right
));
1951 sscanf(keywords
[i
+4], "%d", &(pU
->ovlyputParams
.rc
.bottom
));
1952 dwFlags
|= MCI_OVLY_RECT
;
1957 case MCI_DEVTYPE_DIGITAL_VIDEO
:
1958 FLAG1("source", MCI_DGV_PUT_SOURCE
);
1959 FLAG1("destination", MCI_DGV_PUT_DESTINATION
);
1960 FLAG1("video", MCI_DGV_PUT_VIDEO
);
1961 FLAG1("frame", MCI_DGV_PUT_FRAME
);
1962 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
1963 sscanf(keywords
[i
+1], "%d", &(pU
->dgvputParams
.rc
.left
));
1964 sscanf(keywords
[i
+2], "%d", &(pU
->dgvputParams
.rc
.top
));
1965 sscanf(keywords
[i
+3], "%d", &(pU
->dgvputParams
.rc
.right
));
1966 sscanf(keywords
[i
+4], "%d", &(pU
->dgvputParams
.rc
.bottom
));
1967 dwFlags
|= MCI_DGV_RECT
;
1976 pU
->dgvputParams
.dwCallback
= hwndCallback
;
1977 res
= mciSendCommandA(wDevID
, MCI_PUT
, dwFlags
, (DWORD
)pU
);
1982 /* palette behaviour changing
1984 * "normal" realize the palette normally
1985 * "background" realize the palette as background palette
1988 MCISTR_Realize(_MCISTR_PROTO_
)
1990 MCI_GENERIC_PARMS
*realizeParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1993 if (uDevTyp
!= MCI_DEVTYPE_ANIMATION
)
1994 return MCIERR_UNSUPPORTED_FUNCTION
;
1995 for (i
= 0; i
< nrofkeywords
; i
++) {
1996 FLAG1("background", MCI_ANIM_REALIZE_BKGD
);
1997 FLAG1("normal", MCI_ANIM_REALIZE_NORM
);
1999 realizeParams
->dwCallback
= hwndCallback
;
2000 res
= mciSendCommandA(wDevID
, MCI_REALIZE
, dwFlags
, (DWORD
)realizeParams
);
2001 free(realizeParams
);
2006 * "algorithm <algorithm>"
2007 * "alignment to <integer>"
2008 * "bass to <factor>"
2009 * "bitspersample to <bit_count>"
2010 * "bytespersec to <integer>"
2015 * "left volume to <factor>"
2020 * "quality <descripto>r"
2025 * "right volume to <factor>"
2026 * "samplespersec to <integer>"
2027 * "source to <sourcename>"
2028 * "stream to <number>"
2029 * "treble to <factor>"
2030 * "volume to <factor>"
2034 * "monitor to type number number"
2036 * "record track track_number off"
2038 * "record track track_number on "
2039 * "source to type number number"
2040 * "track track_number off"
2041 * "track track_number on"
2044 MCISTR_SetAudio(_MCISTR_PROTO_
)
2046 MCI_DGV_SETAUDIO_PARMSA setaudioParams
;
2049 if (uDevTyp
!= MCI_DEVTYPE_DIGITAL_VIDEO
)
2050 return MCIERR_UNSUPPORTED_FUNCTION
;
2052 setaudioParams
.dwCallback
= hwndCallback
;
2054 for (i
= 0; i
< nrofkeywords
; ) {
2055 if (!STRCMP(keywords
[i
], "algorithm") && (i
+1 < nrofkeywords
)) {
2056 setaudioParams
.lpstrAlgorithm
= strdup(keywords
[i
+1]);
2057 dwFlags
|= MCI_DGV_SETAUDIO_ALG
;
2061 #define MSAI2(str1, str2, flag) \
2062 if ( !STRCMP(keywords[i], str1) && (i+2 < nrofkeywords) && \
2063 !STRCMP(keywords[i+1], str2)) { \
2064 dwFlags |= MCI_DGV_SETAUDIO_ITEM; \
2065 setaudioParams.dwItem = flag; \
2066 sscanf(keywords[i+2], "%lu", &setaudioParams.dwValue); \
2070 #define MSAI3(str1, str2, str3, flag) \
2071 if ( !STRCMP(keywords[i], str1) && (i+3 < nrofkeywords) && \
2072 !STRCMP(keywords[i+1], str2) && !STRCMP(keywords[i+2], str3)) { \
2073 dwFlags |= MCI_DGV_SETAUDIO_ITEM; \
2074 setaudioParams.dwItem = flag; \
2075 sscanf(keywords[i+3], "%lu", &setaudioParams.dwValue); \
2079 MSAI2("alignment", "to", MCI_DGV_SETAUDIO_BLOCKALIGN
);
2080 MSAI2("bass", "to", MCI_DGV_SETAUDIO_BASS
);
2081 MSAI2("bitspersample", "to", MCI_DGV_SETAUDIO_BITSPERSAMPLE
);
2082 MSAI2("bytespersec", "to", MCI_DGV_SETAUDIO_AVGBYTESPERSEC
);
2083 MSAI2("samplespersec", "to", MCI_DGV_SETAUDIO_SAMPLESPERSEC
);
2084 MSAI2("stream", "to", MCI_DGV_SETAUDIO_STREAM
);
2085 MSAI2("treble", "to", MCI_DGV_SETAUDIO_TREBLE
);
2086 MSAI2("volume", "to", MCI_DGV_SETAUDIO_VOLUME
);
2087 MSAI3("input", "bass", "to", MCI_DGV_SETAUDIO_BASS
|MCI_DGV_SETAUDIO_INPUT
);
2088 MSAI3("input", "treble", "to", MCI_DGV_SETAUDIO_TREBLE
|MCI_DGV_SETAUDIO_INPUT
);
2089 MSAI3("input", "volume", "to", MCI_DGV_SETAUDIO_VOLUME
|MCI_DGV_SETAUDIO_INPUT
);
2090 MSAI3("output", "bass", "to", MCI_DGV_SETAUDIO_BASS
|MCI_DGV_SETAUDIO_OUTPUT
);
2091 MSAI3("output", "treble", "to", MCI_DGV_SETAUDIO_TREBLE
|MCI_DGV_SETAUDIO_OUTPUT
);
2092 MSAI3("output", "volume", "to", MCI_DGV_SETAUDIO_VOLUME
|MCI_DGV_SETAUDIO_OUTPUT
);
2094 FLAG1("clocktime", MCI_DGV_SETAUDIO_CLOCKTIME
);
2095 FLAG2("left", "off", MCI_DGV_SETAUDIO_LEFT
|MCI_SET_OFF
);
2096 FLAG2("left", "on", MCI_DGV_SETAUDIO_LEFT
|MCI_SET_ON
);
2097 if (!STRCMP(keywords
[i
], "left") && (i
+3 < nrofkeywords
) &&
2098 !STRCMP(keywords
[i
+1], "volume") && !STRCMP(keywords
[i
+2], "to")) {
2099 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
| MCI_DGV_SETAUDIO_VALUE
| MCI_DGV_SETAUDIO_LEFT
;
2100 setaudioParams
.dwItem
= MCI_DGV_SETAUDIO_VOLUME
;
2101 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwValue
);
2105 FLAG1("off", MCI_SET_OFF
);
2106 FLAG1("on", MCI_SET_ON
);
2107 if (!STRCMP(keywords
[i
], "over") && (i
+1 < nrofkeywords
)) {
2108 dwFlags
|= MCI_DGV_SETAUDIO_OVER
;
2109 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwOver
);
2113 if (!STRCMP(keywords
[i
], "quality") && (i
+1 < nrofkeywords
)) {
2114 setaudioParams
.lpstrQuality
= strdup(keywords
[i
+1]);
2115 dwFlags
|= MCI_DGV_SETAUDIO_QUALITY
;
2119 FLAG2("record", "off", MCI_DGV_SETAUDIO_RECORD
|MCI_SET_OFF
);
2120 FLAG2("record", "on", MCI_DGV_SETAUDIO_RECORD
|MCI_SET_ON
);
2121 FLAG2("right", "off", MCI_DGV_SETAUDIO_RIGHT
|MCI_SET_OFF
);
2122 FLAG2("right", "on", MCI_DGV_SETAUDIO_RIGHT
|MCI_SET_ON
);
2123 if (!STRCMP(keywords
[i
], "right") && (i
+3 < nrofkeywords
) &&
2124 !STRCMP(keywords
[i
+1], "volume") && !STRCMP(keywords
[i
+2], "to")) {
2125 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
| MCI_DGV_SETAUDIO_VALUE
| MCI_DGV_SETAUDIO_RIGHT
;
2126 setaudioParams
.dwItem
= MCI_DGV_SETAUDIO_VOLUME
;
2127 sscanf(keywords
[i
+3], "%lu", &setaudioParams
.dwValue
);
2131 if (!STRCMP(keywords
[i
], "source") && (i
+2 < nrofkeywords
) && !STRCMP(keywords
[i
+1], "to")) {
2132 dwFlags
|= MCI_DGV_SETAUDIO_ITEM
;
2133 setaudioParams
.dwItem
|= MCI_DGV_SETAUDIO_SOURCE
;
2134 if (!STRCMP(keywords
[i
+2], "left")) {
2135 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_LEFT
;
2136 } else if (!STRCMP(keywords
[i
+2], "right")) {
2137 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_RIGHT
;
2138 } else if (!STRCMP(keywords
[i
+2], "average")) {
2139 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_AVERAGE
;
2140 } else if (!STRCMP(keywords
[i
+2], "stereo")) {
2141 setaudioParams
.dwValue
|= MCI_DGV_SETAUDIO_SOURCE_STEREO
;
2143 res
= MCIERR_UNSUPPORTED_FUNCTION
;
2150 res
= mciSendCommandA(wDevID
, MCI_SETAUDIO
, dwFlags
, (DWORD
)&setaudioParams
);
2151 free(setaudioParams
.lpstrAlgorithm
);
2152 free(setaudioParams
.lpstrQuality
);
2156 /* videodisc spinning
2161 MCISTR_Spin(_MCISTR_PROTO_
)
2163 MCI_GENERIC_PARMS
*spinParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
2166 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
2167 return MCIERR_UNSUPPORTED_FUNCTION
;
2168 for (i
= 0; i
< nrofkeywords
; i
++) {
2169 FLAG1("up", MCI_VD_SPIN_UP
);
2170 FLAG1("down", MCI_VD_SPIN_UP
);
2172 spinParams
->dwCallback
= hwndCallback
;
2173 res
= mciSendCommandA(wDevID
, MCI_SPIN
, dwFlags
, (DWORD
)spinParams
);
2178 /* step single frames
2179 * "reverse" optional flag
2180 * "by <nr>" for <nr> frames
2183 MCISTR_Step(_MCISTR_PROTO_
) {
2185 MCI_ANIM_STEP_PARMS animstepParams
;
2186 MCI_VD_STEP_PARMS vdstepParams
;
2188 union U
*pU
= xmalloc(sizeof(union U
));
2191 for (i
= 0; i
< nrofkeywords
; ) {
2193 case MCI_DEVTYPE_ANIMATION
:
2194 FLAG1("reverse", MCI_ANIM_STEP_REVERSE
);
2195 if (!STRCMP(keywords
[i
], "by") && (i
+1 < nrofkeywords
)) {
2196 sscanf(keywords
[i
+1], "%ld", &(pU
->animstepParams
.dwFrames
));
2197 dwFlags
|= MCI_ANIM_STEP_FRAMES
;
2202 case MCI_DEVTYPE_VIDEODISC
:
2203 FLAG1("reverse", MCI_VD_STEP_REVERSE
);
2204 if (!STRCMP(keywords
[i
], "by") && (i
+1 < nrofkeywords
)) {
2205 sscanf(keywords
[i
+1], "%ld", &(pU
->vdstepParams
.dwFrames
));
2206 dwFlags
|= MCI_VD_STEP_FRAMES
;
2214 pU
->animstepParams
.dwCallback
= hwndCallback
;
2215 res
= mciSendCommandA(wDevID
, MCI_STEP
, dwFlags
, (DWORD
)pU
);
2220 /* update animation window
2222 * "at <left> <top> <right> <bottom>" only in this rectangle
2223 * "hdc" device context
2226 MCISTR_Update(_MCISTR_PROTO_
) {
2228 LPMCI_ANIM_UPDATE_PARMS updateParams
= xmalloc(sizeof(MCI_ANIM_UPDATE_PARMS
));
2230 for (i
= 0; i
< nrofkeywords
; ) {
2231 if (!STRCMP(keywords
[i
], "at") && (i
+4 < nrofkeywords
)) {
2232 sscanf(keywords
[i
+1], "%d", &(updateParams
->rc
.left
));
2233 sscanf(keywords
[i
+2], "%d", &(updateParams
->rc
.top
));
2234 sscanf(keywords
[i
+3], "%d", &(updateParams
->rc
.right
));
2235 sscanf(keywords
[i
+4], "%d", &(updateParams
->rc
.bottom
));
2236 dwFlags
|= MCI_ANIM_RECT
;
2240 if (!STRCMP(keywords
[i
], "hdc") && (i
+1 < nrofkeywords
)) {
2241 dwFlags
|= MCI_ANIM_UPDATE_HDC
;
2242 sscanf(keywords
[i
+1], "%d", &(updateParams
->hDC
));
2248 updateParams
->dwCallback
= hwndCallback
;
2249 res
= mciSendCommandA(wDevID
, MCI_UPDATE
, dwFlags
, (DWORD
)updateParams
);
2254 /* where command for animation and overlay drivers.
2255 * just returns the specified rectangle as a string
2264 MCISTR_Where(_MCISTR_PROTO_
) {
2266 MCI_ANIM_RECT_PARMS animwhereParams
;
2267 MCI_OVLY_RECT_PARMS ovlywhereParams
;
2269 union U
* pU
= xmalloc(sizeof(union U
));
2272 for (i
= 0; i
< nrofkeywords
; i
++) {
2274 case MCI_DEVTYPE_ANIMATION
:
2275 FLAG1("source", MCI_ANIM_WHERE_SOURCE
);
2276 FLAG1("destination", MCI_ANIM_WHERE_DESTINATION
);
2278 case MCI_DEVTYPE_OVERLAY
:
2279 FLAG1("source", MCI_OVLY_WHERE_SOURCE
);
2280 FLAG1("destination", MCI_OVLY_WHERE_DESTINATION
);
2281 FLAG1("video", MCI_OVLY_WHERE_VIDEO
);
2282 FLAG1("frame", MCI_OVLY_WHERE_FRAME
);
2286 pU
->animwhereParams
.dwCallback
= hwndCallback
;
2287 res
= mciSendCommandA(wDevID
, MCI_WHERE
, dwFlags
, (DWORD
)pU
);
2291 case MCI_DEVTYPE_ANIMATION
:
2292 sprintf(buf
, "%d %d %d %d",
2293 pU
->animwhereParams
.rc
.left
,
2294 pU
->animwhereParams
.rc
.top
,
2295 pU
->animwhereParams
.rc
.right
,
2296 pU
->animwhereParams
.rc
.bottom
2299 case MCI_DEVTYPE_OVERLAY
:
2300 sprintf(buf
, "%d %d %d %d",
2301 pU
->ovlywhereParams
.rc
.left
,
2302 pU
->ovlywhereParams
.rc
.top
,
2303 pU
->ovlywhereParams
.rc
.right
,
2304 pU
->ovlywhereParams
.rc
.bottom
2307 default:strcpy(buf
, "0 0 0 0");break;
2316 MCISTR_Window(_MCISTR_PROTO_
) {
2318 MCI_ANIM_WINDOW_PARMSA animwindowParams
;
2319 MCI_OVLY_WINDOW_PARMSA ovlywindowParams
;
2320 MCI_DGV_WINDOW_PARMSA dgvwindowParams
;
2322 union U
* pU
= xmalloc(sizeof(union U
));
2327 for (i
= 0; i
< nrofkeywords
; ) {
2329 case MCI_DEVTYPE_ANIMATION
:
2330 if (!STRCMP(keywords
[i
], "handle") && (i
+1 < nrofkeywords
)) {
2331 dwFlags
|= MCI_ANIM_WINDOW_HWND
;
2332 if (!STRCMP(keywords
[i
+1], "default"))
2333 pU
->animwindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
2335 sscanf(keywords
[i
+1], "%d", &(pU
->animwindowParams
.hWnd
));
2339 if (!STRCMP(keywords
[i
], "state") && (i
+1 < nrofkeywords
)) {
2340 dwFlags
|= MCI_ANIM_WINDOW_STATE
;
2341 if (!STRCMP(keywords
[i
+1], "hide"))
2342 pU
->animwindowParams
.nCmdShow
= SW_HIDE
;
2343 if (!STRCMP(keywords
[i
+1], "iconic"))
2344 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2345 if (!STRCMP(keywords
[i
+1], "minimized"))
2346 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2347 if (!STRCMP(keywords
[i
+1], "maximized"))
2348 pU
->animwindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2349 if (!STRCMP(keywords
[i
+1], "minimize"))
2350 pU
->animwindowParams
.nCmdShow
= SW_MINIMIZE
;
2351 if (!STRCMP(keywords
[i
+1], "normal"))
2352 pU
->animwindowParams
.nCmdShow
= SW_NORMAL
;
2353 if (!STRCMP(keywords
[i
+1], "restore"))
2354 pU
->animwindowParams
.nCmdShow
= SW_NORMAL
;
2355 if (!STRCMP(keywords
[i
+1], "show"))
2356 pU
->animwindowParams
.nCmdShow
= SW_SHOW
;
2357 if (!STRCMP(keywords
[i
+1], "no") && (i
+2 < nrofkeywords
)) {
2358 if (!STRCMP(keywords
[i
+2], "active"))
2359 pU
->animwindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2360 if (!STRCMP(keywords
[i
+2], "action"))
2361 pU
->animwindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2367 /* text is enclosed in " ... " as it seems */
2368 if (!STRCMP(keywords
[i
], "text")) {
2369 if (keywords
[i
+1][0] != '"') {
2373 dwFlags
|= MCI_ANIM_WINDOW_TEXT
;
2374 pU
->animwindowParams
.lpstrText
= _MCISTR_Unquote(keywords
[i
+1]);
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")) {
2420 if (keywords
[i
+1][0] != '"') {
2424 dwFlags
|= MCI_DGV_WINDOW_TEXT
;
2425 pU
->dgvwindowParams
.lpstrText
= _MCISTR_Unquote(keywords
[i
+1]);
2431 case MCI_DEVTYPE_OVERLAY
:
2432 if (!STRCMP(keywords
[i
], "handle") && (i
+1 < nrofkeywords
)) {
2433 dwFlags
|= MCI_OVLY_WINDOW_HWND
;
2434 if (!STRCMP(keywords
[i
+1], "default"))
2435 pU
->ovlywindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
2437 sscanf(keywords
[i
+1], "%d", &(pU
->ovlywindowParams
.hWnd
));
2441 if (!STRCMP(keywords
[i
], "state") && (i
+1 < nrofkeywords
)) {
2442 dwFlags
|= MCI_OVLY_WINDOW_STATE
;
2443 if (!STRCMP(keywords
[i
+1], "hide"))
2444 pU
->ovlywindowParams
.nCmdShow
= SW_HIDE
;
2445 if (!STRCMP(keywords
[i
+1], "iconic"))
2446 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2447 if (!STRCMP(keywords
[i
+1], "minimized"))
2448 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2449 if (!STRCMP(keywords
[i
+1], "maximized"))
2450 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2451 if (!STRCMP(keywords
[i
+1], "minimize"))
2452 pU
->ovlywindowParams
.nCmdShow
= SW_MINIMIZE
;
2453 if (!STRCMP(keywords
[i
+1], "normal"))
2454 pU
->ovlywindowParams
.nCmdShow
= SW_NORMAL
;
2455 if (!STRCMP(keywords
[i
+1], "show"))
2456 pU
->ovlywindowParams
.nCmdShow
= SW_SHOW
;
2457 if (!STRCMP(keywords
[i
+1], "no") && (i
+2 < nrofkeywords
)) {
2458 if (!STRCMP(keywords
[i
+2], "active"))
2459 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2460 if (!STRCMP(keywords
[i
+2], "action"))
2461 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2467 /* text is enclosed in " ... " as it seems */
2468 if (!STRCMP(keywords
[i
], "text")) {
2469 if (keywords
[i
+1][0] != '"') {
2473 dwFlags
|= MCI_OVLY_WINDOW_TEXT
;
2474 pU
->ovlywindowParams
.lpstrText
= _MCISTR_Unquote(keywords
[i
+1]);
2478 FLAG1("stretch", MCI_OVLY_WINDOW_ENABLE_STRETCH
);
2483 pU
->animwindowParams
.dwCallback
= hwndCallback
;
2484 res
= mciSendCommandA(wDevID
, MCI_WINDOW
, dwFlags
, (DWORD
)pU
);
2490 struct _MCISTR_cmdtable
{
2492 DWORD (*fun
)(_MCISTR_PROTO_
);
2493 } MCISTR_cmdtable
[]={
2494 {"break", MCISTR_Break
},
2495 {"capability", MCISTR_Capability
},
2496 {"close", MCISTR_Close
},
2497 {"cue", MCISTR_Cue
},
2498 {"delete", MCISTR_Delete
},
2499 {"escape", MCISTR_Escape
},
2500 {"freeze", MCISTR_Freeze
},
2501 {"info", MCISTR_Info
},
2502 {"load", MCISTR_Load
},
2503 {"open", MCISTR_Open
},
2504 {"pause", MCISTR_Pause
},
2505 {"play", MCISTR_Play
},
2506 {"put", MCISTR_Put
},
2507 {"realize", MCISTR_Realize
},
2508 {"record", MCISTR_Record
},
2509 {"resume", MCISTR_Resume
},
2510 {"save", MCISTR_Save
},
2511 {"seek", MCISTR_Seek
},
2512 {"set", MCISTR_Set
},
2513 {"setaudio", MCISTR_SetAudio
},
2514 {"spin", MCISTR_Spin
},
2515 {"status", MCISTR_Status
},
2516 {"step", MCISTR_Step
},
2517 {"stop", MCISTR_Stop
},
2518 {"sysinfo", MCISTR_Sysinfo
},
2519 {"unfreeze", MCISTR_Unfreeze
},
2520 {"update", MCISTR_Update
},
2521 {"where", MCISTR_Where
},
2522 {"window", MCISTR_Window
},
2526 /**************************************************************************
2527 * mciSendString16 [MMSYSTEM.702]
2529 /* The usercode sends a string with a command (and flags) expressed in
2530 * words in it... We do our best to call appropriate drivers,
2531 * and return a errorcode AND a readable string (if lpstrRS != NULL)
2532 * Info gathered by watching cool134.exe and from Borland's mcistrwh.hlp
2534 /* FIXME: "all" is a valid devicetype and we should access all devices if
2535 * it is used. (imagine "close all"). Not implemented yet.
2537 DWORD WINAPI
mciSendString16(LPCSTR lpstrCommand
, LPSTR lpstrReturnString
,
2538 UINT16 uReturnLength
, HWND16 hwndCallback
)
2540 char *cmd
, *dev
, *args
, **keywords
;
2541 WORD uDevTyp
= 0, wDevID
= 0;
2543 int res
= 0, i
, nrofkeywords
;
2545 TRACE(mci
, "('%s', %p, %d, %X)\n",
2546 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2548 /* format is <command> <device> <optargs> */
2549 cmd
= strdup(lpstrCommand
);
2550 dev
= strchr(cmd
, ' ');
2553 return MCIERR_MISSING_DEVICE_NAME
;
2556 args
= strchr(dev
, ' ');
2562 while (*++args
== ' ');
2564 i
= 1;/* nrofkeywords = nrofspaces+1 */
2566 while ((s
= strchr(s
, ' ')) != NULL
) {
2568 while (*++s
== ' ');
2569 /* see if we have a quoted string */
2571 s
= strchr(s
+1, '"');
2572 if (!s
|| s
[1] != ' ') {
2573 /* missed closing '"'*/
2575 return MCIERR_NO_CLOSING_QUOTE
;
2579 keywords
= (char**)xmalloc(sizeof(char*) * (i
+ 2));
2583 while (s
&& i
< nrofkeywords
) {
2586 if ((s
= strchr(s
+1, '"')) != NULL
) s
++;
2592 while (*++s
== ' ');
2594 TRACE(mci
, "[%d] => '%s'\n", i
-1, keywords
[i
-1]);
2599 keywords
= (char**)xmalloc(sizeof(char*));
2602 dwFlags
= 0; /* default flags */
2603 for (i
= 0; i
< nrofkeywords
;) {
2604 if (!STRCMP(keywords
[i
], "wait")) {
2605 dwFlags
|= MCI_WAIT
;
2606 memcpy(keywords
+i
, keywords
+(i
+1), (nrofkeywords
-i
-1) * sizeof(char*));
2610 if (!STRCMP(keywords
[i
], "notify")) {
2611 dwFlags
|= MCI_NOTIFY
;
2612 memcpy(keywords
+i
, keywords
+(i
+1), (nrofkeywords
-i
-1) * sizeof(char*));
2619 /* determine wDevID and uDevTyp for all commands except "open" */
2620 if (STRCMP(cmd
, "open") != 0) {
2621 wDevID
= mciGetDeviceIDA(dev
);
2623 TRACE(mci
, "Device '%s' not found!\n", dev
);
2624 res
= MCIERR_INVALID_DEVICE_NAME
;
2627 uDevTyp
= MCI_GetDrv(wDevID
)->modp
.wType
;
2630 if (lpstrReturnString
&& uReturnLength
> 0)
2631 *lpstrReturnString
= 0;
2633 for (i
= 0; MCISTR_cmdtable
[i
].cmd
!= NULL
; i
++) {
2634 if (!STRCMP(MCISTR_cmdtable
[i
].cmd
, cmd
)) {
2635 res
= MCISTR_cmdtable
[i
].fun(wDevID
, uDevTyp
, lpstrReturnString
,
2636 uReturnLength
, dev
, (LPSTR
*)keywords
,
2637 nrofkeywords
, dwFlags
, hwndCallback
);
2641 if (MCISTR_cmdtable
[i
].cmd
== NULL
) {
2642 FIXME(mci
, "('%s', %p, %u, %X): unimplemented, please report.\n",
2643 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2644 res
= MCIERR_MISSING_COMMAND_STRING
;
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(mci
, "(%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 ? */