1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
6 * Copyright 1995 Marcus Meissner
8 /* FIXME: special commands of device drivers should be handled by those drivers
11 /* FIXME: this current implementation does not allow commands like
12 * capability <filename> can play
13 * which is allowed by the MCI standard.
20 #include <sys/ioctl.h>
27 #include "multimedia.h"
32 extern struct WINE_MCIDRIVER mciDrv
[MAXMCIDRIVERS
];
34 #define MCI_GetDrv(wDevID) (&mciDrv[MCI_DevIDToIndex(wDevID)])
35 #define MCI_GetOpenDrv(wDevID) (&(MCI_GetDrv(wDevID)->mop))
37 LONG WINAPI
DrvDefDriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
38 DWORD dwParam1
, DWORD dwParam2
);
40 /* The reason why I just don't lowercase the keywords array in
41 * mciSendString is left as an exercise to the reader.
43 #define STRCMP(x,y) lstrcmpi32A(x,y)
45 /* standard functionparameters for all functions */
46 #define _MCISTR_PROTO_ \
47 WORD wDevID,WORD uDevTyp,LPSTR lpstrReturnString,UINT16 uReturnLength,\
48 LPCSTR dev,LPSTR *keywords,UINT16 nrofkeywords,DWORD dwFlags,\
51 /* copy string to return pointer including necessary checks
52 * for use in mciSendString()
54 #define _MCI_STR(s) do {\
55 TRACE(mci,"->returns '%s'\n",s);\
56 if (lpstrReturnString) {\
57 lstrcpyn32A(lpstrReturnString,s,uReturnLength);\
58 TRACE(mci,"-->'%s'\n",lpstrReturnString);\
62 /* print a DWORD in the specified timeformat */
64 _MCISTR_printtf(char *buf
,UINT16 uDevType
,DWORD timef
,DWORD val
) {
67 case MCI_FORMAT_MILLISECONDS
:
68 case MCI_FORMAT_FRAMES
:
69 case MCI_FORMAT_BYTES
:
70 case MCI_FORMAT_SAMPLES
:
71 case MCI_VD_FORMAT_TRACK
:
72 /*case MCI_SEQ_FORMAT_SONGPTR: sameas MCI_VD_FORMAT_TRACK */
73 sprintf(buf
,"%ld",val
);
76 /* well, the macros have the same content*/
79 sprintf(buf
,"%d:%d:%d",
86 sprintf(buf
,"%d:%d:%d:%d",
94 FIXME(mci
, "missing timeformat for %ld, report.\n",timef
);
95 strcpy(buf
,"0"); /* hmm */
100 /* possible different return types */
101 #define _MCISTR_int 1
102 #define _MCISTR_time 2
103 #define _MCISTR_bool 3
104 #define _MCISTR_tfname 4
105 #define _MCISTR_mode 5
106 #define _MCISTR_divtype 6
107 #define _MCISTR_seqtype 7
108 #define _MCISTR_vdmtype 8
109 #define _MCISTR_devtype 9
112 _MCISTR_convreturn(int type
,DWORD dwReturn
,LPSTR lpstrReturnString
,
113 WORD uReturnLength
,WORD uDevTyp
,int timef
116 case _MCISTR_vdmtype
:
118 case MCI_VD_MEDIA_CLV
:_MCI_STR("CLV");break;
119 case MCI_VD_MEDIA_CAV
:_MCI_STR("CAV");break;
121 case MCI_VD_MEDIA_OTHER
:_MCI_STR("other");break;
124 case _MCISTR_seqtype
:
126 case MCI_SEQ_NONE
:_MCI_STR("none");break;
127 case MCI_SEQ_SMPTE
:_MCI_STR("smpte");break;
128 case MCI_SEQ_FILE
:_MCI_STR("file");break;
129 case MCI_SEQ_MIDI
:_MCI_STR("midi");break;
130 default:FIXME(mci
,"missing sequencer mode %ld\n",dwReturn
);
135 case MCI_MODE_NOT_READY
:_MCI_STR("not ready");break;
136 case MCI_MODE_STOP
:_MCI_STR("stopped");break;
137 case MCI_MODE_PLAY
:_MCI_STR("playing");break;
138 case MCI_MODE_RECORD
:_MCI_STR("recording");break;
139 case MCI_MODE_SEEK
:_MCI_STR("seeking");break;
140 case MCI_MODE_PAUSE
:_MCI_STR("paused");break;
141 case MCI_MODE_OPEN
:_MCI_STR("open");break;
153 sprintf(buf
,"%ld",dwReturn
);
159 _MCISTR_printtf(buf
,uDevTyp
,timef
,dwReturn
);
165 case MCI_FORMAT_MILLISECONDS
:_MCI_STR("milliseconds");break;
166 case MCI_FORMAT_FRAMES
:_MCI_STR("frames");break;
167 case MCI_FORMAT_BYTES
:_MCI_STR("bytes");break;
168 case MCI_FORMAT_SAMPLES
:_MCI_STR("samples");break;
169 case MCI_FORMAT_HMS
:_MCI_STR("hms");break;
170 case MCI_FORMAT_MSF
:_MCI_STR("msf");break;
171 case MCI_FORMAT_TMSF
:_MCI_STR("tmsf");break;
173 FIXME(mci
,"missing timefmt for %d, report.\n",timef
);
177 case _MCISTR_divtype
:
179 case MCI_SEQ_DIV_PPQN
:_MCI_STR("PPQN");break;
180 case MCI_SEQ_DIV_SMPTE_24
:_MCI_STR("SMPTE 24 frame");break;
181 case MCI_SEQ_DIV_SMPTE_25
:_MCI_STR("SMPTE 25 frame");break;
182 case MCI_SEQ_DIV_SMPTE_30
:_MCI_STR("SMPTE 30 frame");break;
183 case MCI_SEQ_DIV_SMPTE_30DROP
:_MCI_STR("SMPTE 30 frame drop");break;
185 case _MCISTR_devtype
:
187 case MCI_DEVTYPE_VCR
:_MCI_STR("vcr");break;
188 case MCI_DEVTYPE_VIDEODISC
:_MCI_STR("videodisc");break;
189 case MCI_DEVTYPE_CD_AUDIO
:_MCI_STR("cd audio");break;
190 case MCI_DEVTYPE_OVERLAY
:_MCI_STR("overlay");break;
191 case MCI_DEVTYPE_DAT
:_MCI_STR("dat");break;
192 case MCI_DEVTYPE_SCANNER
:_MCI_STR("scanner");break;
193 case MCI_DEVTYPE_ANIMATION
:_MCI_STR("animation");break;
194 case MCI_DEVTYPE_DIGITAL_VIDEO
:_MCI_STR("digital video");break;
195 case MCI_DEVTYPE_OTHER
:_MCI_STR("other");break;
196 case MCI_DEVTYPE_WAVEFORM_AUDIO
:_MCI_STR("waveform audio");break;
197 case MCI_DEVTYPE_SEQUENCER
:_MCI_STR("sequencer");break;
198 default:FIXME(mci
,"unknown device type %ld, report.\n",
203 FIXME(mci
,"unknown resulttype %d, report.\n",type
);
208 #define FLAG1(str,flag) \
209 if (!STRCMP(keywords[i],str)) {\
214 #define FLAG2(str1,str2,flag) \
215 if (!STRCMP(keywords[i],str1) && (i+1<nrofkeywords) && !STRCMP(keywords[i+1],str2)) {\
221 /* All known subcommands are implemented in single functions to avoid
222 * bloat and a xxxx lines long mciSendString(). All commands are of the
223 * format MCISTR_Cmd(_MCISTR_PROTO_) where _MCISTR_PROTO_ is the above
224 * defined line of arguments. (This is just for easy enhanceability.)
225 * All functions return the MCIERR_ errorvalue as DWORD. Returnvalues
226 * for the calls are in lpstrReturnString (If I mention return values
227 * in function headers, I mean returnvalues in lpstrReturnString.)
228 * Integers are sprintf("%d")ed integers. Boolean values are
229 * "true" and "false".
230 * timeformat depending values are "%d" "%d:%d" "%d:%d:%d" "%d:%d:%d:%d"
231 * FIXME: is above line correct?
233 * Preceding every function is a list of implemented/known arguments.
234 * Feel free to add missing arguments.
239 * Opens the specified MCI driver.
243 * "alias <aliasname>"
244 * "element <elementname>"
247 * "buffer <nrBytesPerSec>"
249 * "nostatic" increaste nr of nonstatic colours
250 * "parent <windowhandle>"
251 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
252 * "style child" WS_CHILD
253 * "style overlap" WS_OVERLAPPED
254 * "style popup" WS_POPUP
256 * "parent <windowhandle>"
257 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
258 * "style child" WS_CHILD
259 * "style overlap" WS_OVERLAPPED
260 * "style popup" WS_POPUP
264 MCISTR_Open(_MCISTR_PROTO_
) {
268 MCI_OPEN_PARMS16 openParams
;
269 MCI_WAVE_OPEN_PARMS16 waveopenParams
;
270 MCI_ANIM_OPEN_PARMS16 animopenParams
;
271 MCI_OVLY_OPEN_PARMS16 ovlyopenParams
;
273 union U
*pU
= xmalloc(sizeof(union U
));
275 pU
->openParams
.lpstrElementName
= NULL
;
279 pU
->openParams
.lpstrElementName
=strdup(s
);
280 dwFlags
|= MCI_OPEN_ELEMENT
;
282 uDevTyp
= MCI_GetDevType(dev
);
284 free(pU
->openParams
.lpstrElementName
);
286 return MCIERR_INVALID_DEVICE_NAME
;
288 wDevID
=MCI_FirstDevID();
289 while(MCI_GetDrv(wDevID
)->modp
.wType
) {
290 wDevID
= MCI_NextDevID(wDevID
);
291 if (!MCI_DevIDValid(wDevID
)) {
292 TRACE(mci
, "MAXMCIDRIVERS reached (%x) !\n", wDevID
);
293 free(pU
->openParams
.lpstrElementName
);
295 return MCIERR_INTERNAL
;
298 MCI_GetDrv(wDevID
)->modp
.wType
= uDevTyp
;
299 MCI_GetDrv(wDevID
)->modp
.wDeviceID
= 0; /* FIXME? for multiple devices */
300 pU
->openParams
.dwCallback
= hwndCallback
;
301 pU
->openParams
.wDeviceID
= wDevID
;
302 pU
->openParams
.wReserved0
= 0;
303 pU
->ovlyopenParams
.dwStyle
= 0;
304 pU
->animopenParams
.dwStyle
= 0;
305 pU
->openParams
.lpstrDeviceType
= strdup(dev
);
306 pU
->openParams
.lpstrAlias
= NULL
;
307 dwFlags
|= MCI_OPEN_TYPE
;
309 while (i
<nrofkeywords
) {
310 FLAG1("shareable",MCI_OPEN_SHAREABLE
);
311 if (!STRCMP(keywords
[i
],"alias") && (i
+1<nrofkeywords
)) {
312 dwFlags
|= MCI_OPEN_ALIAS
;
313 pU
->openParams
.lpstrAlias
=strdup(keywords
[i
+1]);
317 if (!STRCMP(keywords
[i
],"element") && (i
+1<nrofkeywords
)) {
318 dwFlags
|= MCI_OPEN_ELEMENT
;
319 pU
->openParams
.lpstrElementName
=strdup(keywords
[i
+1]);
324 case MCI_DEVTYPE_ANIMATION
:
325 case MCI_DEVTYPE_DIGITAL_VIDEO
:
326 FLAG1("nostatic",MCI_ANIM_OPEN_NOSTATIC
);
327 if (!STRCMP(keywords
[i
],"parent") && (i
+1<nrofkeywords
)) {
328 dwFlags
|= MCI_ANIM_OPEN_PARENT
;
329 sscanf(keywords
[i
+1],"%hu",&(pU
->animopenParams
.hWndParent
));
333 if (!STRCMP(keywords
[i
],"style") && (i
+1<nrofkeywords
)) {
336 dwFlags
|= MCI_ANIM_OPEN_WS
;
337 if (!STRCMP(keywords
[i
+1],"popup")) {
338 pU
->animopenParams
.dwStyle
|= WS_POPUP
;
339 } else if (!STRCMP(keywords
[i
+1],"overlap")) {
340 pU
->animopenParams
.dwStyle
|= WS_OVERLAPPED
;
341 } else if (!STRCMP(keywords
[i
+1],"child")) {
342 pU
->animopenParams
.dwStyle
|= WS_CHILD
;
343 } else if (sscanf(keywords
[i
+1],"%ld",&st
)) {
344 pU
->animopenParams
.dwStyle
|= st
;
346 FIXME(mci
,"unknown 'style' keyword %s, please report.\n",keywords
[i
+1]);
351 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
352 if (!STRCMP(keywords
[i
],"buffer") && (i
+1<nrofkeywords
)) {
353 dwFlags
|= MCI_WAVE_OPEN_BUFFER
;
354 sscanf(keywords
[i
+1],"%ld",&(pU
->waveopenParams
.dwBufferSeconds
));
357 case MCI_DEVTYPE_OVERLAY
:
358 /* looks just like anim, but without NOSTATIC */
359 if (!STRCMP(keywords
[i
],"parent") && (i
+1<nrofkeywords
)) {
360 dwFlags
|= MCI_OVLY_OPEN_PARENT
;
361 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlyopenParams
.hWndParent
));
365 if (!STRCMP(keywords
[i
],"style") && (i
+1<nrofkeywords
)) {
368 dwFlags
|= MCI_OVLY_OPEN_WS
;
369 if (!STRCMP(keywords
[i
+1],"popup")) {
370 pU
->ovlyopenParams
.dwStyle
|= WS_POPUP
;
371 } else if (!STRCMP(keywords
[i
+1],"overlap")) {
372 pU
->ovlyopenParams
.dwStyle
|= WS_OVERLAPPED
;
373 } else if (!STRCMP(keywords
[i
+1],"child")) {
374 pU
->ovlyopenParams
.dwStyle
|= WS_CHILD
;
375 } else if (sscanf(keywords
[i
+1],"%ld",&st
)) {
376 pU
->ovlyopenParams
.dwStyle
|= st
;
378 FIXME(mci
,"unknown 'style' keyword %s, please report.\n",keywords
[i
+1]);
384 FIXME(mci
,"unknown parameter passed %s, please report.\n",
388 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_OPEN
, dwFlags
, (DWORD
)pU
);
391 memcpy(MCI_GetOpenDrv(wDevID
),&pU
->openParams
,sizeof(MCI_OPEN_PARMS16
));
393 free(pU
->openParams
.lpstrElementName
);
394 free(pU
->openParams
.lpstrDeviceType
);
395 free(pU
->openParams
.lpstrAlias
);
401 /* A help function for a lot of others ...
402 * for instance status/play/record/seek etc.
405 _MCISTR_determine_timeformat(LPCSTR dev
,WORD wDevID
,WORD uDevTyp
,int *timef
)
408 DWORD dwFlags
= MCI_STATUS_ITEM
;
409 MCI_STATUS_PARMS
*statusParams
= xmalloc(sizeof(MCI_STATUS_PARMS
));
411 if (!statusParams
) return 0;
412 statusParams
->dwItem
= MCI_STATUS_TIME_FORMAT
;
413 statusParams
->dwReturn
= 0;
414 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_STATUS
, dwFlags
, (DWORD
)statusParams
);
416 if (res
==0) *timef
= statusParams
->dwReturn
;
421 /* query status of MCI drivers
424 * "mode" - returns "not ready" "paused" "playing" "stopped" "open"
425 * "parked" "recording" "seeking" ....
427 * "current track" - returns current track as integer
428 * "length [track <nr>]" - returns length [of track <nr>] in current
430 * "number of tracks" - returns number of tracks as integer
431 * "position [track <nr>]" - returns position [in track <nr>] in current
433 * "ready" - checks if device is ready to play, -> bool
434 * "start position" - returns start position in timeformat
435 * "time format" - returns timeformat (list of possible values:
436 * "ms" "msf" "milliseconds" "hmsf" "tmsf" "frames"
437 * "bytes" "samples" "hms")
438 * "media present" - returns if media is present as bool
440 * "forward" - returns "true" if device is playing forwards
441 * "speed" - returns speed for device
442 * "palette handle" - returns palette handle
443 * "window handle" - returns window handle
444 * "stretch" - returns stretch bool
446 * "division type" - ? returns "PPQN" "SMPTE 24 frame"
447 * "SMPTE 25 frame" "SMPTE 30 frame" "SMPTE 30 drop frame"
448 * "tempo" - current tempo in (PPQN? speed in frames, SMPTE*? speed in hsmf)
449 * "offset" - offset in dito.
450 * "port" - midi port as integer
451 * "slave" - slave device ("midi","file","none","smpte")
452 * "master" - masterdevice (dito.)
454 * "window handle" - see animation
457 * "speed" - speed as integer
458 * "forward" - returns bool (when playing forward)
459 * "side" - returns 1 or 2
460 * "media type" - returns "CAV" "CLV" "other"
461 * "disc size" - returns "8" or "12"
463 * "input" - base queries on input set
464 * "output" - base queries on output set
465 * "format tag" - return integer format tag
466 * "channels" - return integer nr of channels
467 * "bytespersec" - return average nr of bytes/sec
468 * "samplespersec" - return nr of samples per sec
469 * "bitspersample" - return bitspersample
470 * "alignment" - return block alignment
471 * "level" - return level?
474 #define ITEM1(str,item,xtype) \
475 if (!STRCMP(keywords[i],str)) {\
476 statusParams->dwItem = item;\
481 #define ITEM2(str1,str2,item,xtype) \
482 if ( !STRCMP(keywords[i],str1) &&\
483 (i+1<nrofkeywords) &&\
484 !STRCMP(keywords[i+1],str2)\
486 statusParams->dwItem = item;\
491 #define ITEM3(str1,str2,str3,item,xtype) \
492 if ( !STRCMP(keywords[i],str1) &&\
493 (i+2<nrofkeywords) &&\
494 !STRCMP(keywords[i+1],str2) &&\
495 !STRCMP(keywords[i+2],str3)\
497 statusParams->dwItem = item;\
503 MCISTR_Status(_MCISTR_PROTO_
) {
504 MCI_STATUS_PARMS
*statusParams
= xmalloc(sizeof(MCI_STATUS_PARMS
));
505 int type
= 0,i
,res
,timef
;
507 statusParams
->dwCallback
= hwndCallback
;
508 dwFlags
|= MCI_STATUS_ITEM
;
509 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
512 statusParams
->dwReturn
= 0;
513 statusParams
->dwItem
= 0;
516 while (i
<nrofkeywords
) {
517 if (!STRCMP(keywords
[i
],"track") && (i
+1<nrofkeywords
)) {
518 sscanf(keywords
[i
+1],"%ld",&(statusParams
->dwTrack
));
519 dwFlags
|= MCI_TRACK
;
523 FLAG1("start",MCI_STATUS_START
);
525 ITEM2("current","track",MCI_STATUS_CURRENT_TRACK
,_MCISTR_time
);
526 ITEM2("time","format",MCI_STATUS_TIME_FORMAT
,_MCISTR_tfname
);
527 ITEM1("ready",MCI_STATUS_READY
,_MCISTR_bool
);
528 ITEM1("mode",MCI_STATUS_MODE
,_MCISTR_mode
);
529 ITEM3("number","of","tracks",MCI_STATUS_NUMBER_OF_TRACKS
,_MCISTR_int
);
530 ITEM1("length",MCI_STATUS_LENGTH
,_MCISTR_time
);
531 ITEM1("position",MCI_STATUS_POSITION
,_MCISTR_time
);
532 ITEM2("media","present",MCI_STATUS_MEDIA_PRESENT
,_MCISTR_bool
);
535 case MCI_DEVTYPE_ANIMATION
:
536 case MCI_DEVTYPE_DIGITAL_VIDEO
:
537 ITEM2("palette","handle",MCI_ANIM_STATUS_HPAL
,_MCISTR_int
);
538 ITEM2("window","handle",MCI_ANIM_STATUS_HWND
,_MCISTR_int
);
539 ITEM1("stretch",MCI_ANIM_STATUS_STRETCH
,_MCISTR_bool
);
540 ITEM1("speed",MCI_ANIM_STATUS_SPEED
,_MCISTR_int
);
541 ITEM1("forward",MCI_ANIM_STATUS_FORWARD
,_MCISTR_bool
);
543 case MCI_DEVTYPE_SEQUENCER
:
544 /* just completing the list, not working correctly */
545 ITEM2("division","type",MCI_SEQ_STATUS_DIVTYPE
,_MCISTR_divtype
);
546 /* tempo ... PPQN in frames/second, SMPTE in hmsf */
547 ITEM1("tempo",MCI_SEQ_STATUS_TEMPO
,_MCISTR_int
);
548 ITEM1("port",MCI_SEQ_STATUS_PORT
,_MCISTR_int
);
549 ITEM1("slave",MCI_SEQ_STATUS_SLAVE
,_MCISTR_seqtype
);
550 ITEM1("master",MCI_SEQ_STATUS_SLAVE
,_MCISTR_seqtype
);
551 /* offset ... PPQN in frames/second, SMPTE in hmsf */
552 ITEM1("offset",MCI_SEQ_STATUS_SLAVE
,_MCISTR_time
);
554 case MCI_DEVTYPE_OVERLAY
:
555 ITEM2("window","handle",MCI_OVLY_STATUS_HWND
,_MCISTR_int
);
556 ITEM1("stretch",MCI_OVLY_STATUS_STRETCH
,_MCISTR_bool
);
558 case MCI_DEVTYPE_VIDEODISC
:
559 ITEM1("speed",MCI_VD_STATUS_SPEED
,_MCISTR_int
);
560 ITEM1("forward",MCI_VD_STATUS_FORWARD
,_MCISTR_bool
);
561 ITEM1("side",MCI_VD_STATUS_SIDE
,_MCISTR_int
);
562 ITEM2("media","type",MCI_VD_STATUS_SIDE
,_MCISTR_vdmtype
);
563 /* returns 8 or 12 */
564 ITEM2("disc","size",MCI_VD_STATUS_DISC_SIZE
,_MCISTR_int
);
566 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
567 /* I am not quite sure if foll. 2 lines are right. */
568 FLAG1("input",MCI_WAVE_INPUT
);
569 FLAG1("output",MCI_WAVE_OUTPUT
);
571 ITEM2("format","tag",MCI_WAVE_STATUS_FORMATTAG
,_MCISTR_int
);
572 ITEM1("channels",MCI_WAVE_STATUS_CHANNELS
,_MCISTR_int
);
573 ITEM1("bytespersec",MCI_WAVE_STATUS_AVGBYTESPERSEC
,_MCISTR_int
);
574 ITEM1("samplespersec",MCI_WAVE_STATUS_SAMPLESPERSEC
,_MCISTR_int
);
575 ITEM1("bitspersample",MCI_WAVE_STATUS_BITSPERSAMPLE
,_MCISTR_int
);
576 ITEM1("alignment",MCI_WAVE_STATUS_BLOCKALIGN
,_MCISTR_int
);
577 ITEM1("level",MCI_WAVE_STATUS_LEVEL
,_MCISTR_int
);
580 FIXME(mci
,"unknown keyword '%s'\n",keywords
[i
]);
583 if (!statusParams
->dwItem
)
584 return MCIERR_MISSING_STRING_ARGUMENT
;
586 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_STATUS
, dwFlags
, (DWORD
)statusParams
);
589 _MCISTR_convreturn(type
,statusParams
->dwReturn
,lpstrReturnString
,uReturnLength
,uDevTyp
,timef
);
597 /* set specified parameters in respective MCI drivers
599 * "door open" eject media or somesuch
600 * "door close" load media
601 * "time format <timeformatname>" "ms" "milliseconds" "msf" "hmsf"
602 * "tmsf" "SMPTE 24" "SMPTE 25" "SMPTE 30"
604 * "audio [all|left|right] [on|off]" sets specified audiochannel on or off
605 * "video [on|off]" sets video on/off
607 * "formattag pcm" sets format to pcm
608 * "formattag <nr>" sets integer formattag value
609 * "any input" accept input from any known source
610 * "any output" output to any known destination
611 * "input <nr>" input from source <nr>
612 * "output <nr>" output to destination <nr>
613 * "channels <nr>" sets nr of channels
614 * "bytespersec <nr>" sets average bytes per second
615 * "samplespersec <nr>" sets average samples per second (1 sample can
617 * "alignment <nr>" sets the blockalignment to <nr>
618 * "bitspersample <nr>" sets the nr of bits per sample
620 * "master [midi|file|smpte|none]" sets the midi master device
621 * "slave [midi|file|smpte|none]" sets the midi master device
622 * "port mapper" midioutput to portmapper
623 * "port <nr>" midioutput to specified port
624 * "tempo <nr>" tempo of track (depends on timeformat/divtype)
625 * "offset <nr>" start offset?
628 MCISTR_Set(_MCISTR_PROTO_
) {
630 MCI_SET_PARMS setParams
;
631 MCI_WAVE_SET_PARMS16 wavesetParams
;
632 MCI_SEQ_SET_PARMS seqsetParams
;
634 union U
*pU
= xmalloc(sizeof(union U
));
637 pU
->setParams
.dwCallback
= hwndCallback
;
639 while (i
<nrofkeywords
) {
640 FLAG2("door","open",MCI_SET_DOOR_OPEN
);
641 FLAG2("door","closed",MCI_SET_DOOR_CLOSED
);
643 if ( !STRCMP(keywords
[i
],"time") &&
644 (i
+2<nrofkeywords
) &&
645 !STRCMP(keywords
[i
+1],"format")
647 dwFlags
|= MCI_SET_TIME_FORMAT
;
649 /* FIXME:is this a shortcut for milliseconds or
650 * minutes:seconds? */
651 if (!STRCMP(keywords
[i
+2],"ms"))
652 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
654 if (!STRCMP(keywords
[i
+2],"milliseconds"))
655 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
656 if (!STRCMP(keywords
[i
+2],"msf"))
657 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MSF
;
658 if (!STRCMP(keywords
[i
+2],"hms"))
659 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_HMS
;
660 if (!STRCMP(keywords
[i
+2],"frames"))
661 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_FRAMES
;
662 if (!STRCMP(keywords
[i
+2],"track"))
663 pU
->setParams
.dwTimeFormat
= MCI_VD_FORMAT_TRACK
;
664 if (!STRCMP(keywords
[i
+2],"bytes"))
665 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_BYTES
;
666 if (!STRCMP(keywords
[i
+2],"samples"))
667 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SAMPLES
;
668 if (!STRCMP(keywords
[i
+2],"tmsf"))
669 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_TMSF
;
670 if ( !STRCMP(keywords
[i
+2],"song") &&
671 (i
+3<nrofkeywords
) &&
672 !STRCMP(keywords
[i
+3],"pointer")
674 pU
->setParams
.dwTimeFormat
= MCI_SEQ_FORMAT_SONGPTR
;
675 if (!STRCMP(keywords
[i
+2],"smpte") && (i
+3<nrofkeywords
)) {
676 if (!STRCMP(keywords
[i
+3],"24"))
677 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_24
;
678 if (!STRCMP(keywords
[i
+3],"25"))
679 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_25
;
680 if (!STRCMP(keywords
[i
+3],"30"))
681 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30
;
682 if (!STRCMP(keywords
[i
+3],"drop") && (i
+4<nrofkeywords
) && !STRCMP(keywords
[i
+4],"30")) {
683 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30DROP
;
692 if (!STRCMP(keywords
[i
],"audio") && (i
+1<nrofkeywords
)) {
693 dwFlags
|= MCI_SET_AUDIO
;
694 if (!STRCMP(keywords
[i
+1],"all"))
695 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_ALL
;
696 if (!STRCMP(keywords
[i
+1],"left"))
697 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_LEFT
;
698 if (!STRCMP(keywords
[i
+1],"right"))
699 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_RIGHT
;
703 FLAG1("video",MCI_SET_VIDEO
);
704 FLAG1("on",MCI_SET_ON
);
705 FLAG1("off",MCI_SET_OFF
);
707 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
708 FLAG2("any","input",MCI_WAVE_SET_ANYINPUT
);
709 FLAG2("any","output",MCI_WAVE_SET_ANYOUTPUT
);
711 if ( !STRCMP(keywords
[i
],"formattag") &&
712 (i
+1<nrofkeywords
) &&
713 !STRCMP(keywords
[i
+1],"pcm")
715 dwFlags
|= MCI_WAVE_SET_FORMATTAG
;
716 pU
->wavesetParams
.wFormatTag
= WAVE_FORMAT_PCM
;
721 /* <keyword> <integer> */
722 #define WII(str,flag,fmt,element) \
723 if (!STRCMP(keywords[i],str) && (i+1<nrofkeywords)) {\
724 sscanf(keywords[i+1],fmt,&(pU->wavesetParams. element ));\
729 WII("formattag",MCI_WAVE_SET_FORMATTAG
,"%hu",wFormatTag
);
730 WII("channels",MCI_WAVE_SET_CHANNELS
,"%hu",nChannels
);
731 WII("bytespersec",MCI_WAVE_SET_AVGBYTESPERSEC
,"%lu",nAvgBytesPerSec
);
732 WII("samplespersec",MCI_WAVE_SET_SAMPLESPERSEC
,"%lu",nSamplesPerSec
);
733 WII("alignment",MCI_WAVE_SET_BLOCKALIGN
,"%hu",nBlockAlign
);
734 WII("bitspersample",MCI_WAVE_SET_BITSPERSAMPLE
,"%hu",wBitsPerSample
);
735 WII("input",MCI_WAVE_INPUT
,"%hu",wInput
);
736 WII("output",MCI_WAVE_OUTPUT
,"%hu",wOutput
);
739 case MCI_DEVTYPE_SEQUENCER
:
740 if (!STRCMP(keywords
[i
],"master") && (i
+1<nrofkeywords
)) {
741 dwFlags
|= MCI_SEQ_SET_MASTER
;
742 if (!STRCMP(keywords
[i
+1],"midi"))
743 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
744 if (!STRCMP(keywords
[i
+1],"file"))
745 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
746 if (!STRCMP(keywords
[i
+1],"smpte"))
747 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
748 if (!STRCMP(keywords
[i
+1],"none"))
749 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
753 if (!STRCMP(keywords
[i
],"slave") && (i
+1<nrofkeywords
)) {
754 dwFlags
|= MCI_SEQ_SET_SLAVE
;
755 if (!STRCMP(keywords
[i
+1],"midi"))
756 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
757 if (!STRCMP(keywords
[i
+1],"file"))
758 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
759 if (!STRCMP(keywords
[i
+1],"smpte"))
760 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
761 if (!STRCMP(keywords
[i
+1],"none"))
762 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
766 if ( !STRCMP(keywords
[i
],"port") &&
767 (i
+1<nrofkeywords
) &&
768 !STRCMP(keywords
[i
+1],"mapper")
770 pU
->seqsetParams
.dwPort
=-1;/* FIXME:not sure*/
771 dwFlags
|= MCI_SEQ_SET_PORT
;
775 #define SII(str,flag,element) \
776 if (!STRCMP(keywords[i],str) && (i+1<nrofkeywords)) {\
777 sscanf(keywords[i+1],"%ld",&(pU->seqsetParams. element ));\
782 SII("tempo",MCI_SEQ_SET_TEMPO
,dwTempo
);
783 SII("port",MCI_SEQ_SET_PORT
,dwPort
);
784 SII("offset",MCI_SEQ_SET_PORT
,dwOffset
);
789 return MCIERR_MISSING_STRING_ARGUMENT
;
790 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_SET
, dwFlags
, (DWORD
)pU
);
797 * "off" disable break
798 * "on <keyid>" enable break on key with keyid
799 * (I strongly suspect, that there is another parameter:
801 * but I don't see it mentioned in my documentation.
805 MCISTR_Break(_MCISTR_PROTO_
)
807 MCI_BREAK_PARMS16
*breakParams
= xmalloc(sizeof(MCI_BREAK_PARMS16
));
810 if (!breakParams
) return 0;
811 /*breakParams.hwndBreak ? */
812 for (i
= 0; i
< nrofkeywords
; i
++) {
813 FLAG1("off",MCI_BREAK_OFF
);
814 if (!strcmp(keywords
[i
],"on") && (nrofkeywords
>i
+1)) {
815 dwFlags
&=~MCI_BREAK_OFF
;
816 dwFlags
|=MCI_BREAK_KEY
;
817 sscanf(keywords
[i
+1],"%hd",&(breakParams
->nVirtKey
));
822 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_BREAK
, dwFlags
, (DWORD
)breakParams
);
827 #define ITEM1(str,item,xtype) \
828 if (!STRCMP(keywords[i],str)) {\
829 gdcParams->dwItem = item;\
834 #define ITEM2(str1,str2,item,xtype) \
835 if ( !STRCMP(keywords[i],str1) &&\
836 (i+1<nrofkeywords) &&\
837 !STRCMP(keywords[i+1],str2)\
839 gdcParams->dwItem = item;\
844 #define ITEM3(str1,str2,str3,item,xtype) \
845 if ( !STRCMP(keywords[i],str1) &&\
846 (i+2<nrofkeywords) &&\
847 !STRCMP(keywords[i+1],str2) &&\
848 !STRCMP(keywords[i+2],str3)\
850 gdcParams->dwItem = item;\
855 /* get device capabilities of MCI drivers
858 * "device type" returns device name as string
859 * "has audio" returns bool
860 * "has video" returns bool
861 * "uses files" returns bool
862 * "compound device" returns bool
863 * "can record" returns bool
864 * "can play" returns bool
865 * "can eject" returns bool
866 * "can save" returns bool
868 * "palettes" returns nr of available palette entries
869 * "windows" returns nr of available windows
870 * "can reverse" returns bool
871 * "can stretch" returns bool
872 * "slow play rate" returns the slow playrate
873 * "fast play rate" returns the fast playrate
874 * "normal play rate" returns the normal playrate
876 * "windows" returns nr of available windows
877 * "can stretch" returns bool
878 * "can freeze" returns bool
880 * "cav" assume CAV discs (default if no disk inserted)
881 * "clv" assume CLV discs
882 * "can reverse" returns bool
883 * "slow play rate" returns the slow playrate
884 * "fast play rate" returns the fast playrate
885 * "normal play rate" returns the normal playrate
887 * "inputs" returns nr of inputdevices
888 * "outputs" returns nr of outputdevices
891 MCISTR_Capability(_MCISTR_PROTO_
) {
892 MCI_GETDEVCAPS_PARMS
*gdcParams
= xmalloc(sizeof(MCI_GETDEVCAPS_PARMS
));
895 gdcParams
->dwCallback
= hwndCallback
;
897 return MCIERR_MISSING_STRING_ARGUMENT
;
898 /* well , thats default */
899 dwFlags
|= MCI_GETDEVCAPS_ITEM
;
900 gdcParams
->dwItem
= 0;
902 while (i
<nrofkeywords
) {
903 ITEM2("device","type",MCI_GETDEVCAPS_DEVICE_TYPE
,_MCISTR_devtype
);
904 ITEM2("has","audio",MCI_GETDEVCAPS_HAS_AUDIO
,_MCISTR_bool
);
905 ITEM2("has","video",MCI_GETDEVCAPS_HAS_VIDEO
,_MCISTR_bool
);
906 ITEM2("uses","files",MCI_GETDEVCAPS_USES_FILES
,_MCISTR_bool
);
907 ITEM2("compound","device",MCI_GETDEVCAPS_COMPOUND_DEVICE
,_MCISTR_bool
);
908 ITEM2("can","record",MCI_GETDEVCAPS_CAN_RECORD
,_MCISTR_bool
);
909 ITEM2("can","play",MCI_GETDEVCAPS_CAN_PLAY
,_MCISTR_bool
);
910 ITEM2("can","eject",MCI_GETDEVCAPS_CAN_EJECT
,_MCISTR_bool
);
911 ITEM2("can","save",MCI_GETDEVCAPS_CAN_SAVE
,_MCISTR_bool
);
913 case MCI_DEVTYPE_ANIMATION
:
914 ITEM1("palettes",MCI_ANIM_GETDEVCAPS_PALETTES
,_MCISTR_int
);
915 ITEM1("windows",MCI_ANIM_GETDEVCAPS_MAX_WINDOWS
,_MCISTR_int
);
916 ITEM2("can","reverse",MCI_ANIM_GETDEVCAPS_CAN_REVERSE
,_MCISTR_bool
);
917 ITEM2("can","stretch",MCI_ANIM_GETDEVCAPS_CAN_STRETCH
,_MCISTR_bool
);
918 ITEM3("slow","play","rate",MCI_ANIM_GETDEVCAPS_SLOW_RATE
,_MCISTR_int
);
919 ITEM3("fast","play","rate",MCI_ANIM_GETDEVCAPS_FAST_RATE
,_MCISTR_int
);
920 ITEM3("normal","play","rate",MCI_ANIM_GETDEVCAPS_NORMAL_RATE
,_MCISTR_int
);
922 case MCI_DEVTYPE_OVERLAY
:
923 ITEM1("windows",MCI_OVLY_GETDEVCAPS_MAX_WINDOWS
,_MCISTR_int
);
924 ITEM2("can","freeze",MCI_OVLY_GETDEVCAPS_CAN_FREEZE
,_MCISTR_bool
);
925 ITEM2("can","stretch",MCI_OVLY_GETDEVCAPS_CAN_STRETCH
,_MCISTR_bool
);
927 case MCI_DEVTYPE_VIDEODISC
:
928 FLAG1("cav",MCI_VD_GETDEVCAPS_CAV
);
929 FLAG1("clv",MCI_VD_GETDEVCAPS_CLV
);
930 ITEM2("can","reverse",MCI_VD_GETDEVCAPS_CAN_REVERSE
,_MCISTR_bool
);
931 ITEM3("slow","play","rate",MCI_VD_GETDEVCAPS_SLOW_RATE
,_MCISTR_int
);
932 ITEM3("fast","play","rate",MCI_VD_GETDEVCAPS_FAST_RATE
,_MCISTR_int
);
933 ITEM3("normal","play","rate",MCI_VD_GETDEVCAPS_NORMAL_RATE
,_MCISTR_int
);
935 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
936 ITEM1("inputs",MCI_WAVE_GETDEVCAPS_INPUTS
,_MCISTR_int
);
937 ITEM1("outputs",MCI_WAVE_GETDEVCAPS_OUTPUTS
,_MCISTR_int
);
942 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_GETDEVCAPS
, dwFlags
, (DWORD
)gdcParams
);
944 /* no timeformat needed */
946 _MCISTR_convreturn( type
, gdcParams
->dwReturn
, lpstrReturnString
,
947 uReturnLength
, uDevTyp
, 0 );
954 /* resumes operation of device. no arguments, no return values */
956 MCISTR_Resume(_MCISTR_PROTO_
)
958 MCI_GENERIC_PARMS
*genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
960 genParams
->dwCallback
= hwndCallback
;
961 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_RESUME
, dwFlags
, (DWORD
)genParams
);
966 /* pauses operation of device. no arguments, no return values */
968 MCISTR_Pause(_MCISTR_PROTO_
)
970 MCI_GENERIC_PARMS
*genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
972 genParams
->dwCallback
= hwndCallback
;
973 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_PAUSE
, dwFlags
, (DWORD
)genParams
);
978 /* stops operation of device. no arguments, no return values */
980 MCISTR_Stop(_MCISTR_PROTO_
)
982 MCI_GENERIC_PARMS
*genParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
984 genParams
->dwCallback
= hwndCallback
;
985 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_STOP
, dwFlags
, (DWORD
)genParams
);
992 * "overwrite" overwrite existing things
993 * "insert" insert at current position
994 * "to <time>" record up to <time> (specified in timeformat)
995 * "from <time>" record from <time> (specified in timeformat)
998 MCISTR_Record(_MCISTR_PROTO_
) {
999 int i
,res
,timef
,nrargs
,j
,k
,a
[4];
1001 MCI_RECORD_PARMS
*recordParams
= xmalloc(sizeof(MCI_RECORD_PARMS
));
1003 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
1004 if (res
) return res
;
1007 case MCI_FORMAT_MILLISECONDS
:
1008 case MCI_FORMAT_FRAMES
:
1009 case MCI_FORMAT_BYTES
:
1010 case MCI_FORMAT_SAMPLES
:
1014 case MCI_FORMAT_HMS
:
1015 case MCI_FORMAT_MSF
:
1016 parsestr
="%d:%d:%d";
1019 case MCI_FORMAT_TMSF
:
1020 parsestr
="%d:%d:%d:%d";
1023 default:FIXME(mci
,"unknown timeformat %d, please report.\n",timef
);
1028 recordParams
->dwCallback
= hwndCallback
;
1030 while (i
<nrofkeywords
) {
1031 if (!strcmp(keywords
[i
],"to") && (i
+1<nrofkeywords
)) {
1033 a
[0]=a
[1]=a
[2]=a
[3]=0;
1034 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1035 /* add up all integers we got, if we have more
1036 * shift them. (Well I should use the macros in
1037 * mmsystem.h, right).
1039 recordParams
->dwTo
=0;
1041 recordParams
->dwTo
+=a
[k
]<<(8*(nrargs
-k
));
1045 if (!strcmp(keywords
[i
],"from") && (i
+1<nrofkeywords
)) {
1046 dwFlags
|= MCI_FROM
;
1047 a
[0]=a
[1]=a
[2]=a
[3]=0;
1048 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1050 recordParams
->dwFrom
=0;
1052 recordParams
->dwFrom
+=a
[k
]<<(8*(nrargs
-k
));
1056 FLAG1("insert",MCI_RECORD_INSERT
);
1057 FLAG1("overwrite",MCI_RECORD_OVERWRITE
);
1060 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_RECORD
, dwFlags
, (DWORD
)recordParams
);
1067 * "to <time>" play up to <time> (specified in set timeformat)
1068 * "from <time>" play from <time> (specified in set timeformat)
1072 * "scan" play as fast as possible (with audio disabled perhaps)
1073 * "reverse" play reverse
1074 * "speed <fps>" play with specified frames per second
1078 * "scan" play as fast as possible (with audio disabled perhaps)
1079 * "reverse" play reverse
1080 * "speed <fps>" play with specified frames per second
1083 MCISTR_Play(_MCISTR_PROTO_
) {
1084 int i
,res
,timef
,nrargs
,j
,k
,a
[4];
1087 MCI_PLAY_PARMS playParams
;
1088 MCI_VD_PLAY_PARMS vdplayParams
;
1089 MCI_ANIM_PLAY_PARMS animplayParams
;
1091 union U
*pU
= xmalloc(sizeof(union U
));
1093 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
1094 if (res
) return res
;
1096 case MCI_FORMAT_MILLISECONDS
:
1097 case MCI_FORMAT_FRAMES
:
1098 case MCI_FORMAT_BYTES
:
1099 case MCI_FORMAT_SAMPLES
:
1103 case MCI_FORMAT_HMS
:
1104 case MCI_FORMAT_MSF
:
1105 parsestr
="%d:%d:%d";
1108 case MCI_FORMAT_TMSF
:
1109 parsestr
="%d:%d:%d:%d";
1112 default:FIXME(mci
,"unknown timeformat %d, please report.\n",timef
);
1117 pU
->playParams
.dwCallback
=hwndCallback
;
1119 while (i
<nrofkeywords
) {
1120 if (!strcmp(keywords
[i
],"to") && (i
+1<nrofkeywords
)) {
1122 a
[0]=a
[1]=a
[2]=a
[3]=0;
1123 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1124 /* add up all integers we got, if we have more
1125 * shift them. (Well I should use the macros in
1126 * mmsystem.h, right).
1128 pU
->playParams
.dwTo
=0;
1130 pU
->playParams
.dwTo
+=a
[k
]<<(8*(nrargs
-k
));
1134 if (!strcmp(keywords
[i
],"from") && (i
+1<nrofkeywords
)) {
1135 dwFlags
|= MCI_FROM
;
1136 a
[0]=a
[1]=a
[2]=a
[3]=0;
1137 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1139 pU
->playParams
.dwFrom
=0;
1141 pU
->playParams
.dwFrom
+=a
[k
]<<(8*(nrargs
-k
));
1146 case MCI_DEVTYPE_VIDEODISC
:
1147 FLAG1("slow",MCI_VD_PLAY_SLOW
);
1148 FLAG1("fast",MCI_VD_PLAY_FAST
);
1149 FLAG1("scan",MCI_VD_PLAY_SCAN
);
1150 FLAG1("reverse",MCI_VD_PLAY_REVERSE
);
1151 if (!STRCMP(keywords
[i
],"speed") && (i
+1<nrofkeywords
)) {
1152 dwFlags
|= MCI_VD_PLAY_SPEED
;
1153 sscanf(keywords
[i
+1],"%ld",&(pU
->vdplayParams
.dwSpeed
));
1158 case MCI_DEVTYPE_ANIMATION
:
1159 FLAG1("slow",MCI_ANIM_PLAY_SLOW
);
1160 FLAG1("fast",MCI_ANIM_PLAY_FAST
);
1161 FLAG1("scan",MCI_ANIM_PLAY_SCAN
);
1162 FLAG1("reverse",MCI_ANIM_PLAY_REVERSE
);
1163 if (!STRCMP(keywords
[i
],"speed") && (i
+1<nrofkeywords
)) {
1164 dwFlags
|= MCI_ANIM_PLAY_SPEED
;
1165 sscanf(keywords
[i
+1],"%ld",&(pU
->animplayParams
.dwSpeed
));
1173 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_PLAY
, dwFlags
, (DWORD
)pU
);
1178 /* seek to a specified position
1180 * "to start" seek to start of medium
1181 * "to end" seek to end of medium
1182 * "to <time>" seek to <time> specified in current timeformat
1185 MCISTR_Seek(_MCISTR_PROTO_
) {
1186 int i
,res
,timef
,nrargs
,j
,k
,a
[4];
1188 MCI_SEEK_PARMS
*seekParams
= xmalloc(sizeof(MCI_SEEK_PARMS
));
1190 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
1191 if (res
) return res
;
1193 case MCI_FORMAT_MILLISECONDS
:
1194 case MCI_FORMAT_FRAMES
:
1195 case MCI_FORMAT_BYTES
:
1196 case MCI_FORMAT_SAMPLES
:
1200 case MCI_FORMAT_HMS
:
1201 case MCI_FORMAT_MSF
:
1202 parsestr
="%d:%d:%d";
1205 case MCI_FORMAT_TMSF
:
1206 parsestr
="%d:%d:%d:%d";
1209 default:FIXME(mci
,"unknown timeformat %d, please report.\n",timef
);
1214 seekParams
->dwCallback
=hwndCallback
;
1216 while (i
<nrofkeywords
) {
1217 if ( !STRCMP(keywords
[i
],"to") && (i
+1<nrofkeywords
)) {
1218 if (!STRCMP(keywords
[i
+1],"start")) {
1219 dwFlags
|=MCI_SEEK_TO_START
;
1224 if (!STRCMP(keywords
[i
+1],"end")) {
1225 dwFlags
|=MCI_SEEK_TO_END
;
1232 a
[0]=a
[1]=a
[2]=a
[3]=0;
1233 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1236 seekParams
->dwTo
+=a
[k
]<<(8*(nrargs
-k
));
1240 case MCI_DEVTYPE_VIDEODISC
:
1241 FLAG1("reverse",MCI_VD_SEEK_REVERSE
);
1246 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_SEEK
, dwFlags
, (DWORD
)seekParams
);
1251 /* close media/driver */
1253 MCISTR_Close(_MCISTR_PROTO_
)
1255 MCI_GENERIC_PARMS
*closeParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1258 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_CLOSE
, dwFlags
, (DWORD
)closeParams
);
1263 /* return information.
1265 * "product" return product name (human readable)
1266 * "file" return filename
1268 * "text" returns text?
1270 * "text" returns text?
1273 MCISTR_Info(_MCISTR_PROTO_
)
1275 MCI_INFO_PARMS16
*infoParams
= xmalloc(sizeof(MCI_INFO_PARMS16
));
1281 while (i
<nrofkeywords
) {
1282 FLAG1("product",MCI_INFO_PRODUCT
);
1283 FLAG1("file",MCI_INFO_FILE
);
1285 case MCI_DEVTYPE_ANIMATION
:
1286 FLAG1("text",MCI_ANIM_INFO_TEXT
);
1288 case MCI_DEVTYPE_OVERLAY
:
1289 FLAG1("text",MCI_OVLY_INFO_TEXT
);
1294 if (dwFlags
== sflags
)
1295 return MCIERR_MISSING_STRING_ARGUMENT
;
1296 /* MCI driver will fill in lpstrReturn, dwRetSize.
1297 * FIXME: I don't know if this is correct behaviour
1299 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_INFO
, dwFlags
, (DWORD
)infoParams
);
1301 _MCI_STR(infoParams
->lpstrReturn
);
1306 /* query MCI driver itself for information
1308 * "installname" return install name of <device> (system.ini)
1309 * "quantity" return nr of installed drivers
1310 * "open" open drivers only (additional flag)
1311 * "name <nr>" return nr of devices with <devicetyp>
1312 * "name all" return nr of all devices
1314 * FIXME: mciSysInfo16() is broken I think.
1317 MCISTR_Sysinfo(_MCISTR_PROTO_
) {
1318 MCI_SYSINFO_PARMS16 sysinfoParams
;
1321 sysinfoParams
.lpstrReturn
= lpstrReturnString
;
1322 sysinfoParams
.dwRetSize
= uReturnLength
;
1323 sysinfoParams
.wDeviceType
= uDevTyp
;
1325 for (i
= 0; i
< nrofkeywords
; i
++) {
1326 FLAG1("installname",MCI_SYSINFO_INSTALLNAME
);
1327 FLAG1("quantity",MCI_SYSINFO_INSTALLNAME
);
1328 FLAG1("open",MCI_SYSINFO_OPEN
);
1329 if (!strcmp(keywords
[i
],"name") && (i
+1<nrofkeywords
)) {
1330 sscanf(keywords
[i
+1],"%ld",&(sysinfoParams
.dwNumber
));
1331 dwFlags
|= MCI_SYSINFO_NAME
;
1335 res
= mciSendCommand16(0, MCI_SYSINFO
, dwFlags
, (DWORD
)&sysinfoParams
);
1337 if (dwFlags
& MCI_SYSINFO_QUANTITY
) {
1340 sprintf(buf
,"%ld",*(long*)lpstrReturnString
);
1343 /* no need to copy anything back, mciSysInfo did it for us */
1348 * Argument: "<filename>"
1349 * Overlay: "at <left> <top> <right> <bottom>" additional
1352 MCISTR_Load(_MCISTR_PROTO_
) {
1354 MCI_LOAD_PARMS16 loadParams
;
1355 MCI_OVLY_LOAD_PARMS16 ovlyloadParams
;
1357 union U
*pU
= xmalloc(sizeof(union U
));
1362 while (i
<nrofkeywords
) {
1364 case MCI_DEVTYPE_OVERLAY
:
1365 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1366 dwFlags
|= MCI_OVLY_RECT
;
1367 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlyloadParams
.rc
.left
));
1368 sscanf(keywords
[i
+2],"%hd",&(pU
->ovlyloadParams
.rc
.top
));
1369 sscanf(keywords
[i
+3],"%hd",&(pU
->ovlyloadParams
.rc
.right
));
1370 sscanf(keywords
[i
+4],"%hd",&(pU
->ovlyloadParams
.rc
.bottom
));
1371 memcpy(keywords
+i
,keywords
+(i
+5),nrofkeywords
-(i
+5));
1376 len
+=strlen(keywords
[i
])+1;
1379 s
=(char*)xmalloc(len
);
1381 while (i
<nrofkeywords
) {
1382 strcat(s
,keywords
[i
]);
1384 if (i
<nrofkeywords
) strcat(s
," ");
1386 pU
->loadParams
.lpfilename
=s
;
1387 dwFlags
|= MCI_LOAD_FILE
;
1388 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_LOAD
, dwFlags
, (DWORD
)pU
);
1395 * Argument: "<filename>"
1396 * Overlay: "at <left> <top> <right> <bottom>" additional
1399 MCISTR_Save(_MCISTR_PROTO_
) {
1401 MCI_SAVE_PARMS saveParams
;
1402 MCI_OVLY_SAVE_PARMS16 ovlysaveParams
;
1404 union U
*pU
= xmalloc(sizeof(union U
));
1409 while (i
<nrofkeywords
) {
1411 case MCI_DEVTYPE_OVERLAY
:
1412 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1413 dwFlags
|= MCI_OVLY_RECT
;
1414 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlysaveParams
.rc
.left
));
1415 sscanf(keywords
[i
+2],"%hd",&(pU
->ovlysaveParams
.rc
.top
));
1416 sscanf(keywords
[i
+3],"%hd",&(pU
->ovlysaveParams
.rc
.right
));
1417 sscanf(keywords
[i
+4],"%hd",&(pU
->ovlysaveParams
.rc
.bottom
));
1418 memcpy(keywords
+i
,keywords
+(i
+5),nrofkeywords
-(i
+5));
1423 len
+=strlen(keywords
[i
])+1;
1426 s
=(char*)xmalloc(len
);
1428 while (i
<nrofkeywords
) {
1429 strcat(s
,keywords
[i
]);
1431 if (i
<nrofkeywords
) strcat(s
," ");
1433 pU
->saveParams
.lpfilename
=s
;
1434 dwFlags
|= MCI_LOAD_FILE
;
1435 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_SAVE
, dwFlags
, (DWORD
)pU
);
1441 /* prepare device for input/output
1442 * (only applyable to waveform audio)
1445 MCISTR_Cue(_MCISTR_PROTO_
) {
1446 MCI_GENERIC_PARMS
*cueParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1449 for (i
= 0; i
< nrofkeywords
; i
++) {
1451 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
1452 FLAG1("input",MCI_WAVE_INPUT
);
1453 FLAG1("output",MCI_WAVE_OUTPUT
);
1457 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_CUE
, dwFlags
, (DWORD
)cueParams
);
1462 /* delete information */
1464 MCISTR_Delete(_MCISTR_PROTO_
) {
1465 int timef
,nrargs
,i
,j
,k
,a
[4],res
;
1467 MCI_WAVE_DELETE_PARMS
*deleteParams
= xmalloc(sizeof(MCI_WAVE_DELETE_PARMS
));
1469 /* only implemented for waveform audio */
1470 if (uDevTyp
!= MCI_DEVTYPE_WAVEFORM_AUDIO
)
1471 return MCIERR_UNSUPPORTED_FUNCTION
; /* well it fits */
1472 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
1473 if (res
) return res
;
1475 case MCI_FORMAT_MILLISECONDS
:
1476 case MCI_FORMAT_FRAMES
:
1477 case MCI_FORMAT_BYTES
:
1478 case MCI_FORMAT_SAMPLES
:
1482 case MCI_FORMAT_HMS
:
1483 case MCI_FORMAT_MSF
:
1484 parsestr
="%d:%d:%d";
1487 case MCI_FORMAT_TMSF
:
1488 parsestr
="%d:%d:%d:%d";
1491 default:FIXME(mci
,"unknown timeformat %d, please report.\n",timef
);
1497 while (i
<nrofkeywords
) {
1498 if (!strcmp(keywords
[i
],"to") && (i
+1<nrofkeywords
)) {
1500 a
[0]=a
[1]=a
[2]=a
[3]=0;
1501 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1502 /* add up all integers we got, if we have more
1503 * shift them. (Well I should use the macros in
1504 * mmsystem.h, right).
1506 deleteParams
->dwTo
=0;
1508 deleteParams
->dwTo
+=a
[k
]<<(8*(nrargs
-k
));
1512 if (!strcmp(keywords
[i
],"from") && (i
+1<nrofkeywords
)) {
1513 dwFlags
|= MCI_FROM
;
1514 a
[0]=a
[1]=a
[2]=a
[3]=0;
1515 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1517 deleteParams
->dwFrom
=0;
1519 deleteParams
->dwFrom
+=a
[k
]<<(8*(nrargs
-k
));
1525 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_DELETE
, dwFlags
, (DWORD
)deleteParams
);
1530 /* send command to device. only applies to videodisc */
1532 MCISTR_Escape(_MCISTR_PROTO_
)
1534 MCI_VD_ESCAPE_PARMS16
*escapeParams
= xmalloc(sizeof(MCI_VD_ESCAPE_PARMS16
));
1538 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
1539 return MCIERR_UNSUPPORTED_FUNCTION
;
1541 while (i
<nrofkeywords
) {
1542 len
+=strlen(keywords
[i
])+1;
1545 s
=(char*)malloc(len
);
1547 while (i
<nrofkeywords
) {
1548 strcat(s
,keywords
[i
]);
1550 if (i
<nrofkeywords
) strcat(s
," ");
1552 escapeParams
->lpstrCommand
= s
;
1553 dwFlags
|= MCI_VD_ESCAPE_STRING
;
1554 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_ESCAPE
, dwFlags
, (DWORD
)escapeParams
);
1560 /* unfreeze [part of] the overlayed video
1561 * only applyable to Overlay devices
1564 MCISTR_Unfreeze(_MCISTR_PROTO_
)
1566 MCI_OVLY_RECT_PARMS16
*unfreezeParams
= xmalloc(sizeof(MCI_OVLY_RECT_PARMS16
));
1569 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1570 return MCIERR_UNSUPPORTED_FUNCTION
;
1571 i
=0;while (i
<nrofkeywords
) {
1572 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1573 sscanf(keywords
[i
+1],"%hd",&(unfreezeParams
->rc
.left
));
1574 sscanf(keywords
[i
+2],"%hd",&(unfreezeParams
->rc
.top
));
1575 sscanf(keywords
[i
+3],"%hd",&(unfreezeParams
->rc
.right
));
1576 sscanf(keywords
[i
+4],"%hd",&(unfreezeParams
->rc
.bottom
));
1577 dwFlags
|= MCI_OVLY_RECT
;
1583 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_UNFREEZE
, dwFlags
, (DWORD
)unfreezeParams
);
1584 free(unfreezeParams
);
1587 /* freeze [part of] the overlayed video
1588 * only applyable to Overlay devices
1591 MCISTR_Freeze(_MCISTR_PROTO_
)
1593 MCI_OVLY_RECT_PARMS16
*freezeParams
= xmalloc(sizeof(MCI_OVLY_RECT_PARMS16
));
1596 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1597 return MCIERR_UNSUPPORTED_FUNCTION
;
1598 i
=0;while (i
<nrofkeywords
) {
1599 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1600 sscanf(keywords
[i
+1],"%hd",&(freezeParams
->rc
.left
));
1601 sscanf(keywords
[i
+2],"%hd",&(freezeParams
->rc
.top
));
1602 sscanf(keywords
[i
+3],"%hd",&(freezeParams
->rc
.right
));
1603 sscanf(keywords
[i
+4],"%hd",&(freezeParams
->rc
.bottom
));
1604 dwFlags
|= MCI_OVLY_RECT
;
1610 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_FREEZE
, dwFlags
, (DWORD
)freezeParams
);
1615 /* copy parts of image to somewhere else
1616 * "source [at <left> <top> <right> <bottom>]" source is framebuffer [or rect]
1617 * "destination [at <left> <top> <right> <bottom>]" destination is framebuffer [or rect]
1619 * "frame [at <left> <top> <right> <bottom>]" frame is framebuffer [or rect]
1620 * where the video input is placed
1621 * "video [at <left> <top> <right> <bottom>]" video is whole video [or rect]
1622 * (defining part of input to
1625 * FIXME: This whole junk is passing multiple rectangles.
1626 * I don't know how to do that with the present interface.
1627 * (Means code below is broken)
1630 MCISTR_Put(_MCISTR_PROTO_
) {
1632 MCI_OVLY_RECT_PARMS16 ovlyputParams
;
1633 MCI_ANIM_RECT_PARMS16 animputParams
;
1635 union U
*pU
= xmalloc(sizeof(union U
));
1637 i
=0;while (i
<nrofkeywords
) {
1639 case MCI_DEVTYPE_ANIMATION
:
1640 FLAG1("source",MCI_ANIM_PUT_SOURCE
);
1641 FLAG1("destination",MCI_ANIM_PUT_DESTINATION
);
1642 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1643 sscanf(keywords
[i
+1],"%hd",&(pU
->animputParams
.rc
.left
));
1644 sscanf(keywords
[i
+2],"%hd",&(pU
->animputParams
.rc
.top
));
1645 sscanf(keywords
[i
+3],"%hd",&(pU
->animputParams
.rc
.right
));
1646 sscanf(keywords
[i
+4],"%hd",&(pU
->animputParams
.rc
.bottom
));
1647 dwFlags
|= MCI_ANIM_RECT
;
1652 case MCI_DEVTYPE_OVERLAY
:
1653 FLAG1("source",MCI_OVLY_PUT_SOURCE
);
1654 FLAG1("destination",MCI_OVLY_PUT_DESTINATION
);
1655 FLAG1("video",MCI_OVLY_PUT_VIDEO
);
1656 FLAG1("frame",MCI_OVLY_PUT_FRAME
);
1657 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1658 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlyputParams
.rc
.left
));
1659 sscanf(keywords
[i
+2],"%hd",&(pU
->ovlyputParams
.rc
.top
));
1660 sscanf(keywords
[i
+3],"%hd",&(pU
->ovlyputParams
.rc
.right
));
1661 sscanf(keywords
[i
+4],"%hd",&(pU
->ovlyputParams
.rc
.bottom
));
1662 dwFlags
|= MCI_OVLY_RECT
;
1670 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_PUT
, dwFlags
, (DWORD
)pU
);
1675 /* palette behaviour changing
1677 * "normal" realize the palette normally
1678 * "background" realize the palette as background palette
1681 MCISTR_Realize(_MCISTR_PROTO_
)
1683 MCI_GENERIC_PARMS
*realizeParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1686 if (uDevTyp
!= MCI_DEVTYPE_ANIMATION
)
1687 return MCIERR_UNSUPPORTED_FUNCTION
;
1689 while (i
<nrofkeywords
) {
1690 FLAG1("background",MCI_ANIM_REALIZE_BKGD
);
1691 FLAG1("normal",MCI_ANIM_REALIZE_NORM
);
1694 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_REALIZE
, dwFlags
, (DWORD
)realizeParams
);
1695 free(realizeParams
);
1699 /* videodisc spinning
1704 MCISTR_Spin(_MCISTR_PROTO_
)
1706 MCI_GENERIC_PARMS
*spinParams
= xmalloc(sizeof(MCI_GENERIC_PARMS
));
1709 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
1710 return MCIERR_UNSUPPORTED_FUNCTION
;
1712 while (i
<nrofkeywords
) {
1713 FLAG1("up",MCI_VD_SPIN_UP
);
1714 FLAG1("down",MCI_VD_SPIN_UP
);
1717 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_SPIN
, dwFlags
, (DWORD
)spinParams
);
1722 /* step single frames
1723 * "reverse" optional flag
1724 * "by <nr>" for <nr> frames
1727 MCISTR_Step(_MCISTR_PROTO_
) {
1729 MCI_ANIM_STEP_PARMS animstepParams
;
1730 MCI_VD_STEP_PARMS vdstepParams
;
1732 union U
*pU
= xmalloc(sizeof(union U
));
1736 while (i
<nrofkeywords
) {
1738 case MCI_DEVTYPE_ANIMATION
:
1739 FLAG1("reverse",MCI_ANIM_STEP_REVERSE
);
1740 if (!STRCMP(keywords
[i
],"by") && (i
+1<nrofkeywords
)) {
1741 sscanf(keywords
[i
+1],"%ld",&(pU
->animstepParams
.dwFrames
));
1742 dwFlags
|= MCI_ANIM_STEP_FRAMES
;
1747 case MCI_DEVTYPE_VIDEODISC
:
1748 FLAG1("reverse",MCI_VD_STEP_REVERSE
);
1749 if (!STRCMP(keywords
[i
],"by") && (i
+1<nrofkeywords
)) {
1750 sscanf(keywords
[i
+1],"%ld",&(pU
->vdstepParams
.dwFrames
));
1751 dwFlags
|= MCI_VD_STEP_FRAMES
;
1759 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_STEP
, dwFlags
, (DWORD
)pU
);
1764 /* update animation window
1766 * "at <left> <top> <right> <bottom>" only in this rectangle
1767 * "hdc" device context
1770 MCISTR_Update(_MCISTR_PROTO_
) {
1772 MCI_ANIM_UPDATE_PARMS16
*updateParams
= xmalloc(sizeof(MCI_ANIM_UPDATE_PARMS16
));
1775 while (i
<nrofkeywords
) {
1776 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1777 sscanf(keywords
[i
+1],"%hd",&(updateParams
->rc
.left
));
1778 sscanf(keywords
[i
+2],"%hd",&(updateParams
->rc
.top
));
1779 sscanf(keywords
[i
+3],"%hd",&(updateParams
->rc
.right
));
1780 sscanf(keywords
[i
+4],"%hd",&(updateParams
->rc
.bottom
));
1781 dwFlags
|= MCI_ANIM_RECT
;
1785 if (!STRCMP(keywords
[i
],"hdc") && (i
+1<nrofkeywords
)) {
1786 dwFlags
|= MCI_ANIM_UPDATE_HDC
;
1787 sscanf(keywords
[i
+1],"%hd",&(updateParams
->hDC
));
1793 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_UPDATE
, dwFlags
, (DWORD
)updateParams
);
1798 /* where command for animation and overlay drivers.
1799 * just returns the specified rectangle as a string
1808 MCISTR_Where(_MCISTR_PROTO_
) {
1810 MCI_ANIM_RECT_PARMS16 animwhereParams
;
1811 MCI_OVLY_RECT_PARMS16 ovlywhereParams
;
1813 union U
*pU
= xmalloc(sizeof(union U
));
1817 while (i
<nrofkeywords
) {
1819 case MCI_DEVTYPE_ANIMATION
:
1820 FLAG1("source",MCI_ANIM_WHERE_SOURCE
);
1821 FLAG1("destination",MCI_ANIM_WHERE_DESTINATION
);
1823 case MCI_DEVTYPE_OVERLAY
:
1824 FLAG1("source",MCI_OVLY_WHERE_SOURCE
);
1825 FLAG1("destination",MCI_OVLY_WHERE_DESTINATION
);
1826 FLAG1("video",MCI_OVLY_WHERE_VIDEO
);
1827 FLAG1("frame",MCI_OVLY_WHERE_FRAME
);
1832 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_WHERE
, dwFlags
, (DWORD
)pU
);
1836 case MCI_DEVTYPE_ANIMATION
:
1837 sprintf(buf
,"%d %d %d %d",
1838 pU
->animwhereParams
.rc
.left
,
1839 pU
->animwhereParams
.rc
.top
,
1840 pU
->animwhereParams
.rc
.right
,
1841 pU
->animwhereParams
.rc
.bottom
1844 case MCI_DEVTYPE_OVERLAY
:
1845 sprintf(buf
,"%d %d %d %d",
1846 pU
->ovlywhereParams
.rc
.left
,
1847 pU
->ovlywhereParams
.rc
.top
,
1848 pU
->ovlywhereParams
.rc
.right
,
1849 pU
->ovlywhereParams
.rc
.bottom
1852 default:strcpy(buf
,"0 0 0 0");break;
1861 MCISTR_Window(_MCISTR_PROTO_
) {
1865 MCI_ANIM_WINDOW_PARMS16 animwindowParams
;
1866 MCI_OVLY_WINDOW_PARMS16 ovlywindowParams
;
1868 union U
*pU
= xmalloc(sizeof(union U
));
1872 while (i
<nrofkeywords
) {
1874 case MCI_DEVTYPE_ANIMATION
:
1875 if (!STRCMP(keywords
[i
],"handle") && (i
+1<nrofkeywords
)) {
1876 dwFlags
|= MCI_ANIM_WINDOW_HWND
;
1877 if (!STRCMP(keywords
[i
+1],"default"))
1878 pU
->animwindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
1880 sscanf(keywords
[i
+1],"%hd",&(pU
->animwindowParams
.hWnd
));
1884 if (!STRCMP(keywords
[i
],"state") && (i
+1<nrofkeywords
)) {
1885 dwFlags
|= MCI_ANIM_WINDOW_STATE
;
1886 if (!STRCMP(keywords
[i
+1],"hide"))
1887 pU
->animwindowParams
.nCmdShow
= SW_HIDE
;
1888 if (!STRCMP(keywords
[i
+1],"iconic"))
1889 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
1890 if (!STRCMP(keywords
[i
+1],"minimized"))
1891 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
1892 if (!STRCMP(keywords
[i
+1],"maximized"))
1893 pU
->animwindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
1894 if (!STRCMP(keywords
[i
+1],"minimize"))
1895 pU
->animwindowParams
.nCmdShow
= SW_MINIMIZE
;
1896 if (!STRCMP(keywords
[i
+1],"normal"))
1897 pU
->animwindowParams
.nCmdShow
= SW_NORMAL
;
1898 if (!STRCMP(keywords
[i
+1],"show"))
1899 pU
->animwindowParams
.nCmdShow
= SW_SHOW
;
1900 if (!STRCMP(keywords
[i
+1],"no") && (i
+2<nrofkeywords
)) {
1901 if (!STRCMP(keywords
[i
+2],"active"))
1902 pU
->animwindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
1903 if (!STRCMP(keywords
[i
+2],"action"))
1904 pU
->animwindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
1910 /* text is enclosed in " ... " as it seems */
1911 if (!STRCMP(keywords
[i
],"text")) {
1915 if (keywords
[i
+1][0]!='"') {
1919 dwFlags
|= MCI_ANIM_WINDOW_TEXT
;
1920 len
= strlen(keywords
[i
+1])+1;
1922 while (j
<nrofkeywords
) {
1923 len
+= strlen(keywords
[j
])+1;
1924 if (strchr(keywords
[j
],'"'))
1928 s
=(char*)xmalloc(len
);
1929 strcpy(s
,keywords
[i
+1]+1);
1933 strcat(s
,keywords
[j
]);
1935 if ((t
=strchr(s
,'"'))) *t
='\0';
1936 /* FIXME: segmented pointer? */
1937 pU
->animwindowParams
.lpstrText
= s
;
1941 FLAG1("stretch",MCI_ANIM_WINDOW_ENABLE_STRETCH
);
1943 case MCI_DEVTYPE_OVERLAY
:
1944 if (!STRCMP(keywords
[i
],"handle") && (i
+1<nrofkeywords
)) {
1945 dwFlags
|= MCI_OVLY_WINDOW_HWND
;
1946 if (!STRCMP(keywords
[i
+1],"default"))
1947 pU
->ovlywindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
1949 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlywindowParams
.hWnd
));
1953 if (!STRCMP(keywords
[i
],"state") && (i
+1<nrofkeywords
)) {
1954 dwFlags
|= MCI_OVLY_WINDOW_STATE
;
1955 if (!STRCMP(keywords
[i
+1],"hide"))
1956 pU
->ovlywindowParams
.nCmdShow
= SW_HIDE
;
1957 if (!STRCMP(keywords
[i
+1],"iconic"))
1958 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
1959 if (!STRCMP(keywords
[i
+1],"minimized"))
1960 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
1961 if (!STRCMP(keywords
[i
+1],"maximized"))
1962 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
1963 if (!STRCMP(keywords
[i
+1],"minimize"))
1964 pU
->ovlywindowParams
.nCmdShow
= SW_MINIMIZE
;
1965 if (!STRCMP(keywords
[i
+1],"normal"))
1966 pU
->ovlywindowParams
.nCmdShow
= SW_NORMAL
;
1967 if (!STRCMP(keywords
[i
+1],"show"))
1968 pU
->ovlywindowParams
.nCmdShow
= SW_SHOW
;
1969 if (!STRCMP(keywords
[i
+1],"no") && (i
+2<nrofkeywords
)) {
1970 if (!STRCMP(keywords
[i
+2],"active"))
1971 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
1972 if (!STRCMP(keywords
[i
+2],"action"))
1973 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
1979 /* text is enclosed in " ... " as it seems */
1980 if (!STRCMP(keywords
[i
],"text")) {
1984 if (keywords
[i
+1][0]!='"') {
1988 dwFlags
|= MCI_OVLY_WINDOW_TEXT
;
1989 len
= strlen(keywords
[i
+1])+1;
1991 while (j
<nrofkeywords
) {
1992 len
+= strlen(keywords
[j
])+1;
1993 if (strchr(keywords
[j
],'"'))
1997 s
=(char*)xmalloc(len
);
1998 strcpy(s
,keywords
[i
+1]+1);
2002 strcat(s
,keywords
[j
]);
2004 if ((t
=strchr(s
,'"'))) *t
='\0';
2005 /* FIXME: segmented pointer? */
2006 pU
->ovlywindowParams
.lpstrText
= s
;
2010 FLAG1("stretch",MCI_OVLY_WINDOW_ENABLE_STRETCH
);
2015 res
= MCI_SendCommand32(MCI_GetDrv(wDevID
)->modp
.wDeviceID
, MCI_WINDOW
, dwFlags
, (DWORD
)pU
);
2021 struct _MCISTR_cmdtable
{
2023 DWORD (*fun
)(_MCISTR_PROTO_
);
2024 } MCISTR_cmdtable
[]={
2025 {"break", MCISTR_Break
},
2026 {"capability", MCISTR_Capability
},
2027 {"close", MCISTR_Close
},
2028 {"cue", MCISTR_Cue
},
2029 {"delete", MCISTR_Delete
},
2030 {"escape", MCISTR_Escape
},
2031 {"freeze", MCISTR_Freeze
},
2032 {"info", MCISTR_Info
},
2033 {"load", MCISTR_Load
},
2034 {"open", MCISTR_Open
},
2035 {"pause", MCISTR_Pause
},
2036 {"play", MCISTR_Play
},
2037 {"put", MCISTR_Put
},
2038 {"realize", MCISTR_Realize
},
2039 {"record", MCISTR_Record
},
2040 {"resume", MCISTR_Resume
},
2041 {"save", MCISTR_Save
},
2042 {"seek", MCISTR_Seek
},
2043 {"set", MCISTR_Set
},
2044 {"spin", MCISTR_Spin
},
2045 {"status", MCISTR_Status
},
2046 {"step", MCISTR_Step
},
2047 {"stop", MCISTR_Stop
},
2048 {"sysinfo", MCISTR_Sysinfo
},
2049 {"unfreeze", MCISTR_Unfreeze
},
2050 {"update", MCISTR_Update
},
2051 {"where", MCISTR_Where
},
2052 {"window", MCISTR_Window
},
2056 /**************************************************************************
2057 * mciSendString16 [MMSYSTEM.702]
2059 /* The usercode sends a string with a command (and flags) expressed in
2060 * words in it... We do our best to call aprobiate drivers,
2061 * and return a errorcode AND a readable string (if lpstrRS!=NULL)
2062 * Info gathered by watching cool134.exe and from Borland's mcistrwh.hlp
2064 /* FIXME: "all" is a valid devicetype and we should access all devices if
2065 * it is used. (imagine "close all"). Not implemented yet.
2067 DWORD WINAPI
mciSendString16(LPCSTR lpstrCommand
, LPSTR lpstrReturnString
,
2068 UINT16 uReturnLength
, HWND16 hwndCallback
)
2070 char *cmd
,*dev
,*args
,**keywords
,*filename
;
2071 WORD uDevTyp
=0,wDevID
=0;
2073 int res
=0,i
,nrofkeywords
;
2075 TRACE(mci
,"('%s', %p, %d, %X)\n",
2076 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2078 /* format is <command> <device> <optargs> */
2079 cmd
=strdup(lpstrCommand
);
2080 dev
=strchr(cmd
,' ');
2083 return MCIERR_MISSING_DEVICE_NAME
;
2086 args
=strchr(dev
,' ');
2087 if (args
!=NULL
) *args
++='\0';
2091 i
=1;/* nrofkeywords = nrofspaces+1 */
2093 while ((s
=strchr(s
,' '))!=NULL
) i
++,s
++;
2094 keywords
=(char**)xmalloc(sizeof(char*)*(i
+2));
2097 while (s
&& i
<nrofkeywords
) {
2105 keywords
=(char**)xmalloc(sizeof(char*));
2107 dwFlags
= 0; /* default flags */
2108 for (i
=0;i
<nrofkeywords
;) {
2109 /* take care, there is also a "device type" capability */
2110 if ((!STRCMP(keywords
[i
],"type")) && (i
<nrofkeywords
-1)) {
2112 dev
= keywords
[i
+1];
2113 memcpy(keywords
+i
,keywords
+(i
+2),(nrofkeywords
-i
-2)*sizeof(char *));
2117 if (!STRCMP(keywords
[i
],"wait")) {
2118 dwFlags
|= MCI_WAIT
;
2119 memcpy(keywords
+i
,keywords
+(i
+1),(nrofkeywords
-i
-1)*sizeof(char *));
2123 if (!STRCMP(keywords
[i
],"notify")) {
2124 dwFlags
|= MCI_NOTIFY
;
2125 memcpy(keywords
+i
,keywords
+(i
+1),(nrofkeywords
-i
-1)*sizeof(char *));
2132 /* determine wDevID and uDevTyp for all commands except "open" */
2133 if (STRCMP(cmd
,"open")!=0) {
2134 wDevID
= MCI_FirstDevID();
2138 dname
=MCI_GetOpenDrv(wDevID
)->lpstrAlias
;
2140 dname
=MCI_GetOpenDrv(wDevID
)->lpstrDeviceType
;
2141 if (dname
!= NULL
&& !STRCMP(dname
,dev
))
2143 wDevID
= MCI_NextDevID(wDevID
);
2144 if (!MCI_DevIDValid(wDevID
)) {
2145 TRACE(mci
, "MAXMCIDRIVERS reached!\n");
2146 free(keywords
);free(cmd
);
2147 return MCIERR_INVALID_DEVICE_NAME
;
2150 uDevTyp
=MCI_GetDrv(wDevID
)->modp
.wType
;
2153 for (i
=0;MCISTR_cmdtable
[i
].cmd
!=NULL
;i
++) {
2154 if (!STRCMP(MCISTR_cmdtable
[i
].cmd
,cmd
)) {
2155 res
=MCISTR_cmdtable
[i
].fun(
2156 wDevID
,uDevTyp
,lpstrReturnString
,
2157 uReturnLength
,dev
,(LPSTR
*)keywords
,nrofkeywords
,
2158 dwFlags
,hwndCallback
2163 if (MCISTR_cmdtable
[i
].cmd
!=NULL
) {
2164 free(keywords
);free(cmd
);
2167 FIXME(mci
,"('%s', %p, %u, %X): unimplemented, please report.\n",
2168 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2169 free(keywords
);free(cmd
);
2170 return MCIERR_MISSING_COMMAND_STRING
;
2173 /**************************************************************************
2174 * mciSendString32A [MMSYSTEM.702][WINMM.51]
2176 DWORD WINAPI
mciSendString32A(LPCSTR lpstrCommand
, LPSTR lpstrReturnString
,
2177 UINT32 uReturnLength
, HWND32 hwndCallback
)
2179 return mciSendString16(lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2182 /**************************************************************************
2183 * mciSendString32W [WINMM.52]
2185 DWORD WINAPI
mciSendString32W(LPCWSTR lpwstrCommand
, LPSTR lpstrReturnString
,
2186 UINT32 uReturnLength
, HWND32 hwndCallback
)
2191 /* FIXME: is there something to do with lpstrReturnString ? */
2192 lpstrCommand
= HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrCommand
);
2193 ret
= mciSendString16(lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2194 HeapFree(GetProcessHeap(), 0, lpstrCommand
);