4 * Copyright 1995 Marcus Meissner
6 /* FIXME: special commands of device drivers should be handled by those drivers
9 /* FIXME: this current implementation does not allow commands like
10 * capability <filename> can play
11 * which is allowed by the MCI standard.
18 #include <sys/ioctl.h>
30 extern struct LINUX_MCIDRIVER mciDrv
[MAXMCIDRIVERS
];
32 #define GetDrv(wDevID) (&mciDrv[MMSYSTEM_DevIDToIndex(wDevID)])
33 #define GetOpenDrv(wDevID) (&(GetDrv(wDevID)->mop))
35 extern int MMSYSTEM_DevIDToIndex(UINT16 wDevID
);
36 extern UINT16
MMSYSTEM_FirstDevID(void);
37 extern UINT16
MMSYSTEM_NextDevID(UINT16 wDevID
);
38 extern BOOL32
MMSYSTEM_DevIDValid(UINT16 wDevID
);
40 LONG WINAPI
DrvDefDriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
41 DWORD dwParam1
, DWORD dwParam2
);
43 LONG
WAVE_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
44 DWORD dwParam1
, DWORD dwParam2
);
45 LONG
MIDI_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
46 DWORD dwParam1
, DWORD dwParam2
);
47 LONG
CDAUDIO_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
48 DWORD dwParam1
, DWORD dwParam2
);
49 LONG
ANIM_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
50 DWORD dwParam1
, DWORD dwParam2
);
52 /* The reason why I just don't lowercase the keywords array in
53 * mciSendString is left as an exercise to the reader.
55 #define STRCMP(x,y) lstrcmpi32A(x,y)
57 /* standard functionparameters for all functions */
58 #define _MCISTR_PROTO_ \
59 WORD wDevID,WORD uDevTyp,LPSTR lpstrReturnString,UINT16 uReturnLength,\
60 LPCSTR dev,LPSTR *keywords,UINT16 nrofkeywords,DWORD dwFlags,\
63 /* copy string to return pointer including necessary checks
64 * for use in mciSendString()
66 #define _MCI_STR(s) do {\
67 TRACE(mci,"->returns '%s'\n",s);\
68 if (lpstrReturnString) {\
69 lstrcpyn32A(lpstrReturnString,s,uReturnLength);\
70 TRACE(mci,"-->'%s'\n",lpstrReturnString);\
74 /* calling DriverProc. We need to pass the struct as SEGMENTED POINTER. */
75 #define _MCI_CALL_DRIVER(cmd,params) \
77 case MCI_DEVTYPE_CD_AUDIO:\
78 res=CDAUDIO_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,cmd,dwFlags, (DWORD)(params));\
80 case MCI_DEVTYPE_WAVEFORM_AUDIO:\
81 res=WAVE_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
83 case MCI_DEVTYPE_SEQUENCER:\
84 res=MIDI_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
86 case MCI_DEVTYPE_ANIMATION:\
87 res=ANIM_DriverProc(GetDrv(wDevID)->modp.wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
89 case MCI_DEVTYPE_DIGITAL_VIDEO:\
90 FIXME(mci,"_MCI_CALL_DRIVER: No DIGITAL_VIDEO yet !\n");\
91 res=MCIERR_DEVICE_NOT_INSTALLED;\
94 /*res = Callbacks->CallDriverProc(GetDrv(wDevID)->driverproc,GetDrv(wDevID)->modp.wDeviceID,GetDrv(wDevID)->hdrv,cmd,dwFlags,(DWORD)(params));\
96 res = MCIERR_DEVICE_NOT_INSTALLED;\
99 /* print a DWORD in the specified timeformat */
101 _MCISTR_printtf(char *buf
,UINT16 uDevType
,DWORD timef
,DWORD val
) {
104 case MCI_FORMAT_MILLISECONDS
:
105 case MCI_FORMAT_FRAMES
:
106 case MCI_FORMAT_BYTES
:
107 case MCI_FORMAT_SAMPLES
:
108 case MCI_VD_FORMAT_TRACK
:
109 /*case MCI_SEQ_FORMAT_SONGPTR: sameas MCI_VD_FORMAT_TRACK */
110 sprintf(buf
,"%ld",val
);
113 /* well, the macros have the same content*/
116 sprintf(buf
,"%d:%d:%d",
122 case MCI_FORMAT_TMSF
:
123 sprintf(buf
,"%d:%d:%d:%d",
125 MCI_TMSF_MINUTE(val
),
126 MCI_TMSF_SECOND(val
),
131 FIXME(mci
, "missing timeformat for %ld, report.\n",timef
);
132 strcpy(buf
,"0"); /* hmm */
137 /* possible different return types */
138 #define _MCISTR_int 1
139 #define _MCISTR_time 2
140 #define _MCISTR_bool 3
141 #define _MCISTR_tfname 4
142 #define _MCISTR_mode 5
143 #define _MCISTR_divtype 6
144 #define _MCISTR_seqtype 7
145 #define _MCISTR_vdmtype 8
146 #define _MCISTR_devtype 9
149 _MCISTR_convreturn(int type
,DWORD dwReturn
,LPSTR lpstrReturnString
,
150 WORD uReturnLength
,WORD uDevTyp
,int timef
153 case _MCISTR_vdmtype
:
155 case MCI_VD_MEDIA_CLV
:_MCI_STR("CLV");break;
156 case MCI_VD_MEDIA_CAV
:_MCI_STR("CAV");break;
158 case MCI_VD_MEDIA_OTHER
:_MCI_STR("other");break;
161 case _MCISTR_seqtype
:
163 case MCI_SEQ_NONE
:_MCI_STR("none");break;
164 case MCI_SEQ_SMPTE
:_MCI_STR("smpte");break;
165 case MCI_SEQ_FILE
:_MCI_STR("file");break;
166 case MCI_SEQ_MIDI
:_MCI_STR("midi");break;
167 default:FIXME(mci
,"missing sequencer mode %ld\n",dwReturn
);
172 case MCI_MODE_NOT_READY
:_MCI_STR("not ready");break;
173 case MCI_MODE_STOP
:_MCI_STR("stopped");break;
174 case MCI_MODE_PLAY
:_MCI_STR("playing");break;
175 case MCI_MODE_RECORD
:_MCI_STR("recording");break;
176 case MCI_MODE_SEEK
:_MCI_STR("seeking");break;
177 case MCI_MODE_PAUSE
:_MCI_STR("paused");break;
178 case MCI_MODE_OPEN
:_MCI_STR("open");break;
190 sprintf(buf
,"%ld",dwReturn
);
196 _MCISTR_printtf(buf
,uDevTyp
,timef
,dwReturn
);
202 case MCI_FORMAT_MILLISECONDS
:_MCI_STR("milliseconds");break;
203 case MCI_FORMAT_FRAMES
:_MCI_STR("frames");break;
204 case MCI_FORMAT_BYTES
:_MCI_STR("bytes");break;
205 case MCI_FORMAT_SAMPLES
:_MCI_STR("samples");break;
206 case MCI_FORMAT_HMS
:_MCI_STR("hms");break;
207 case MCI_FORMAT_MSF
:_MCI_STR("msf");break;
208 case MCI_FORMAT_TMSF
:_MCI_STR("tmsf");break;
210 FIXME(mci
,"missing timefmt for %d, report.\n",timef
);
214 case _MCISTR_divtype
:
216 case MCI_SEQ_DIV_PPQN
:_MCI_STR("PPQN");break;
217 case MCI_SEQ_DIV_SMPTE_24
:_MCI_STR("SMPTE 24 frame");break;
218 case MCI_SEQ_DIV_SMPTE_25
:_MCI_STR("SMPTE 25 frame");break;
219 case MCI_SEQ_DIV_SMPTE_30
:_MCI_STR("SMPTE 30 frame");break;
220 case MCI_SEQ_DIV_SMPTE_30DROP
:_MCI_STR("SMPTE 30 frame drop");break;
222 case _MCISTR_devtype
:
224 case MCI_DEVTYPE_VCR
:_MCI_STR("vcr");break;
225 case MCI_DEVTYPE_VIDEODISC
:_MCI_STR("videodisc");break;
226 case MCI_DEVTYPE_CD_AUDIO
:_MCI_STR("cd audio");break;
227 case MCI_DEVTYPE_OVERLAY
:_MCI_STR("overlay");break;
228 case MCI_DEVTYPE_DAT
:_MCI_STR("dat");break;
229 case MCI_DEVTYPE_SCANNER
:_MCI_STR("scanner");break;
230 case MCI_DEVTYPE_ANIMATION
:_MCI_STR("animation");break;
231 case MCI_DEVTYPE_DIGITAL_VIDEO
:_MCI_STR("digital video");break;
232 case MCI_DEVTYPE_OTHER
:_MCI_STR("other");break;
233 case MCI_DEVTYPE_WAVEFORM_AUDIO
:_MCI_STR("waveform audio");break;
234 case MCI_DEVTYPE_SEQUENCER
:_MCI_STR("sequencer");break;
235 default:FIXME(mci
,"unknown device type %ld, report.\n",
240 FIXME(mci
,"unknown resulttype %d, report.\n",type
);
245 #define FLAG1(str,flag) \
246 if (!STRCMP(keywords[i],str)) {\
251 #define FLAG2(str1,str2,flag) \
252 if (!STRCMP(keywords[i],str1) && (i+1<nrofkeywords) && !STRCMP(keywords[i+1],str2)) {\
258 /* All known subcommands are implemented in single functions to avoid
259 * bloat and a xxxx lines long mciSendString(). All commands are of the
260 * format MCISTR_Cmd(_MCISTR_PROTO_) where _MCISTR_PROTO_ is the above
261 * defined line of arguments. (This is just for easy enhanceability.)
262 * All functions return the MCIERR_ errorvalue as DWORD. Returnvalues
263 * for the calls are in lpstrReturnString (If I mention return values
264 * in function headers, I mean returnvalues in lpstrReturnString.)
265 * Integers are sprintf("%d")ed integers. Boolean values are
266 * "true" and "false".
267 * timeformat depending values are "%d" "%d:%d" "%d:%d:%d" "%d:%d:%d:%d"
268 * FIXME: is above line correct?
270 * Preceding every function is a list of implemented/known arguments.
271 * Feel free to add missing arguments.
276 * Opens the specified MCI driver.
280 * "alias <aliasname>"
281 * "element <elementname>"
284 * "buffer <nrBytesPerSec>"
286 * "nostatic" increaste nr of nonstatic colours
287 * "parent <windowhandle>"
288 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
289 * "style child" WS_CHILD
290 * "style overlap" WS_OVERLAPPED
291 * "style popup" WS_POPUP
293 * "parent <windowhandle>"
294 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
295 * "style child" WS_CHILD
296 * "style overlap" WS_OVERLAPPED
297 * "style popup" WS_POPUP
301 MCISTR_Open(_MCISTR_PROTO_
) {
305 MCI_OPEN_PARMS16 openParams
;
306 MCI_WAVE_OPEN_PARMS16 waveopenParams
;
307 MCI_ANIM_OPEN_PARMS16 animopenParams
;
308 MCI_OVLY_OPEN_PARMS16 ovlyopenParams
;
310 union U
*pU
= SEGPTR_NEW(union U
);
312 pU
->openParams
.lpstrElementName
= NULL
;
316 pU
->openParams
.lpstrElementName
=(LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(s
));
317 dwFlags
|= MCI_OPEN_ELEMENT
;
319 if (!STRCMP(dev
,"cdaudio")) {
320 uDevTyp
=MCI_DEVTYPE_CD_AUDIO
;
321 } else if (!STRCMP(dev
,"waveaudio")) {
322 uDevTyp
=MCI_DEVTYPE_WAVEFORM_AUDIO
;
323 } else if (!STRCMP(dev
,"sequencer")) {
324 uDevTyp
=MCI_DEVTYPE_SEQUENCER
;
325 } else if (!STRCMP(dev
,"animation1")) {
326 uDevTyp
=MCI_DEVTYPE_ANIMATION
;
327 } else if (!STRCMP(dev
,"avivideo")) {
328 uDevTyp
=MCI_DEVTYPE_DIGITAL_VIDEO
;
330 SEGPTR_FREE(PTR_SEG_TO_LIN(pU
->openParams
.lpstrElementName
));
332 return MCIERR_INVALID_DEVICE_NAME
;
334 wDevID
=MMSYSTEM_FirstDevID();
335 while(GetDrv(wDevID
)->modp
.wType
) {
336 wDevID
= MMSYSTEM_NextDevID(wDevID
);
337 if (!MMSYSTEM_DevIDValid(wDevID
)) {
338 TRACE(mci
, "MAXMCIDRIVERS reached (%x) !\n", wDevID
);
339 SEGPTR_FREE(PTR_SEG_TO_LIN(pU
->openParams
.lpstrElementName
));
341 return MCIERR_INTERNAL
;
344 GetDrv(wDevID
)->modp
.wType
= uDevTyp
;
345 GetDrv(wDevID
)->modp
.wDeviceID
= 0; /* FIXME? for multiple devices */
346 pU
->openParams
.dwCallback
= hwndCallback
;
347 pU
->openParams
.wDeviceID
= wDevID
;
348 pU
->ovlyopenParams
.dwStyle
= 0;
349 pU
->animopenParams
.dwStyle
= 0;
350 pU
->openParams
.lpstrDeviceType
= (LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(dev
));
351 pU
->openParams
.lpstrAlias
= NULL
;
352 dwFlags
|= MCI_OPEN_TYPE
;
354 while (i
<nrofkeywords
) {
355 FLAG1("shareable",MCI_OPEN_SHAREABLE
);
356 if (!STRCMP(keywords
[i
],"alias") && (i
+1<nrofkeywords
)) {
357 dwFlags
|= MCI_OPEN_ALIAS
;
358 pU
->openParams
.lpstrAlias
=(LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(keywords
[i
+1]));
362 if (!STRCMP(keywords
[i
],"element") && (i
+1<nrofkeywords
)) {
363 dwFlags
|= MCI_OPEN_ELEMENT
;
364 pU
->openParams
.lpstrElementName
=(LPSTR
)SEGPTR_GET(SEGPTR_STRDUP(keywords
[i
+1]));
369 case MCI_DEVTYPE_ANIMATION
:
370 case MCI_DEVTYPE_DIGITAL_VIDEO
:
371 FLAG1("nostatic",MCI_ANIM_OPEN_NOSTATIC
);
372 if (!STRCMP(keywords
[i
],"parent") && (i
+1<nrofkeywords
)) {
373 dwFlags
|= MCI_ANIM_OPEN_PARENT
;
374 sscanf(keywords
[i
+1],"%hu",&(pU
->animopenParams
.hWndParent
));
378 if (!STRCMP(keywords
[i
],"style") && (i
+1<nrofkeywords
)) {
381 dwFlags
|= MCI_ANIM_OPEN_WS
;
382 if (!STRCMP(keywords
[i
+1],"popup")) {
383 pU
->animopenParams
.dwStyle
|= WS_POPUP
;
384 } else if (!STRCMP(keywords
[i
+1],"overlap")) {
385 pU
->animopenParams
.dwStyle
|= WS_OVERLAPPED
;
386 } else if (!STRCMP(keywords
[i
+1],"child")) {
387 pU
->animopenParams
.dwStyle
|= WS_CHILD
;
388 } else if (sscanf(keywords
[i
+1],"%ld",&st
)) {
389 pU
->animopenParams
.dwStyle
|= st
;
391 FIXME(mci
,"unknown 'style' keyword %s, please report.\n",keywords
[i
+1]);
396 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
397 if (!STRCMP(keywords
[i
],"buffer") && (i
+1<nrofkeywords
)) {
398 dwFlags
|= MCI_WAVE_OPEN_BUFFER
;
399 sscanf(keywords
[i
+1],"%ld",&(pU
->waveopenParams
.dwBufferSeconds
));
402 case MCI_DEVTYPE_OVERLAY
:
403 /* looks just like anim, but without NOSTATIC */
404 if (!STRCMP(keywords
[i
],"parent") && (i
+1<nrofkeywords
)) {
405 dwFlags
|= MCI_OVLY_OPEN_PARENT
;
406 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlyopenParams
.hWndParent
));
410 if (!STRCMP(keywords
[i
],"style") && (i
+1<nrofkeywords
)) {
413 dwFlags
|= MCI_OVLY_OPEN_WS
;
414 if (!STRCMP(keywords
[i
+1],"popup")) {
415 pU
->ovlyopenParams
.dwStyle
|= WS_POPUP
;
416 } else if (!STRCMP(keywords
[i
+1],"overlap")) {
417 pU
->ovlyopenParams
.dwStyle
|= WS_OVERLAPPED
;
418 } else if (!STRCMP(keywords
[i
+1],"child")) {
419 pU
->ovlyopenParams
.dwStyle
|= WS_CHILD
;
420 } else if (sscanf(keywords
[i
+1],"%ld",&st
)) {
421 pU
->ovlyopenParams
.dwStyle
|= st
;
423 FIXME(mci
,"unknown 'style' keyword %s, please report.\n",keywords
[i
+1]);
429 FIXME(mci
,"unknown parameter passed %s, please report.\n",
433 _MCI_CALL_DRIVER( MCI_OPEN
, SEGPTR_GET(pU
) );
435 memcpy(GetOpenDrv(wDevID
),&pU
->openParams
,sizeof(MCI_OPEN_PARMS16
));
437 SEGPTR_FREE(PTR_SEG_TO_LIN(pU
->openParams
.lpstrElementName
));
438 SEGPTR_FREE(PTR_SEG_TO_LIN(pU
->openParams
.lpstrDeviceType
));
439 SEGPTR_FREE(PTR_SEG_TO_LIN(pU
->openParams
.lpstrAlias
));
445 /* A help function for a lot of others ...
446 * for instance status/play/record/seek etc.
449 _MCISTR_determine_timeformat(LPCSTR dev
,WORD wDevID
,WORD uDevTyp
,int *timef
)
452 DWORD dwFlags
= MCI_STATUS_ITEM
;
453 MCI_STATUS_PARMS
*statusParams
= SEGPTR_NEW(MCI_STATUS_PARMS
);
455 if (!statusParams
) return 0;
456 statusParams
->dwItem
= MCI_STATUS_TIME_FORMAT
;
457 statusParams
->dwReturn
= 0;
458 _MCI_CALL_DRIVER( MCI_STATUS
, SEGPTR_GET(statusParams
) );
459 if (res
==0) *timef
= statusParams
->dwReturn
;
460 SEGPTR_FREE(statusParams
);
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?
517 #define ITEM1(str,item,xtype) \
518 if (!STRCMP(keywords[i],str)) {\
519 statusParams->dwItem = item;\
524 #define ITEM2(str1,str2,item,xtype) \
525 if ( !STRCMP(keywords[i],str1) &&\
526 (i+1<nrofkeywords) &&\
527 !STRCMP(keywords[i+1],str2)\
529 statusParams->dwItem = item;\
534 #define ITEM3(str1,str2,str3,item,xtype) \
535 if ( !STRCMP(keywords[i],str1) &&\
536 (i+2<nrofkeywords) &&\
537 !STRCMP(keywords[i+1],str2) &&\
538 !STRCMP(keywords[i+2],str3)\
540 statusParams->dwItem = item;\
546 MCISTR_Status(_MCISTR_PROTO_
) {
547 MCI_STATUS_PARMS
*statusParams
= SEGPTR_NEW(MCI_STATUS_PARMS
);
548 int type
= 0,i
,res
,timef
;
550 statusParams
->dwCallback
= hwndCallback
;
551 dwFlags
|= MCI_STATUS_ITEM
;
552 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
555 statusParams
->dwReturn
= 0;
556 statusParams
->dwItem
= 0;
559 while (i
<nrofkeywords
) {
560 if (!STRCMP(keywords
[i
],"track") && (i
+1<nrofkeywords
)) {
561 sscanf(keywords
[i
+1],"%ld",&(statusParams
->dwTrack
));
562 dwFlags
|= MCI_TRACK
;
566 FLAG1("start",MCI_STATUS_START
);
568 ITEM2("current","track",MCI_STATUS_CURRENT_TRACK
,_MCISTR_time
);
569 ITEM2("time","format",MCI_STATUS_TIME_FORMAT
,_MCISTR_tfname
);
570 ITEM1("ready",MCI_STATUS_READY
,_MCISTR_bool
);
571 ITEM1("mode",MCI_STATUS_MODE
,_MCISTR_mode
);
572 ITEM3("number","of","tracks",MCI_STATUS_NUMBER_OF_TRACKS
,_MCISTR_int
);
573 ITEM1("length",MCI_STATUS_LENGTH
,_MCISTR_time
);
574 ITEM1("position",MCI_STATUS_POSITION
,_MCISTR_time
);
575 ITEM2("media","present",MCI_STATUS_MEDIA_PRESENT
,_MCISTR_bool
);
578 case MCI_DEVTYPE_ANIMATION
:
579 case MCI_DEVTYPE_DIGITAL_VIDEO
:
580 ITEM2("palette","handle",MCI_ANIM_STATUS_HPAL
,_MCISTR_int
);
581 ITEM2("window","handle",MCI_ANIM_STATUS_HWND
,_MCISTR_int
);
582 ITEM1("stretch",MCI_ANIM_STATUS_STRETCH
,_MCISTR_bool
);
583 ITEM1("speed",MCI_ANIM_STATUS_SPEED
,_MCISTR_int
);
584 ITEM1("forward",MCI_ANIM_STATUS_FORWARD
,_MCISTR_bool
);
586 case MCI_DEVTYPE_SEQUENCER
:
587 /* just completing the list, not working correctly */
588 ITEM2("division","type",MCI_SEQ_STATUS_DIVTYPE
,_MCISTR_divtype
);
589 /* tempo ... PPQN in frames/second, SMPTE in hmsf */
590 ITEM1("tempo",MCI_SEQ_STATUS_TEMPO
,_MCISTR_int
);
591 ITEM1("port",MCI_SEQ_STATUS_PORT
,_MCISTR_int
);
592 ITEM1("slave",MCI_SEQ_STATUS_SLAVE
,_MCISTR_seqtype
);
593 ITEM1("master",MCI_SEQ_STATUS_SLAVE
,_MCISTR_seqtype
);
594 /* offset ... PPQN in frames/second, SMPTE in hmsf */
595 ITEM1("offset",MCI_SEQ_STATUS_SLAVE
,_MCISTR_time
);
597 case MCI_DEVTYPE_OVERLAY
:
598 ITEM2("window","handle",MCI_OVLY_STATUS_HWND
,_MCISTR_int
);
599 ITEM1("stretch",MCI_OVLY_STATUS_STRETCH
,_MCISTR_bool
);
601 case MCI_DEVTYPE_VIDEODISC
:
602 ITEM1("speed",MCI_VD_STATUS_SPEED
,_MCISTR_int
);
603 ITEM1("forward",MCI_VD_STATUS_FORWARD
,_MCISTR_bool
);
604 ITEM1("side",MCI_VD_STATUS_SIDE
,_MCISTR_int
);
605 ITEM2("media","type",MCI_VD_STATUS_SIDE
,_MCISTR_vdmtype
);
606 /* returns 8 or 12 */
607 ITEM2("disc","size",MCI_VD_STATUS_DISC_SIZE
,_MCISTR_int
);
609 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
610 /* I am not quite sure if foll. 2 lines are right. */
611 FLAG1("input",MCI_WAVE_INPUT
);
612 FLAG1("output",MCI_WAVE_OUTPUT
);
614 ITEM2("format","tag",MCI_WAVE_STATUS_FORMATTAG
,_MCISTR_int
);
615 ITEM1("channels",MCI_WAVE_STATUS_CHANNELS
,_MCISTR_int
);
616 ITEM1("bytespersec",MCI_WAVE_STATUS_AVGBYTESPERSEC
,_MCISTR_int
);
617 ITEM1("samplespersec",MCI_WAVE_STATUS_SAMPLESPERSEC
,_MCISTR_int
);
618 ITEM1("bitspersample",MCI_WAVE_STATUS_BITSPERSAMPLE
,_MCISTR_int
);
619 ITEM1("alignment",MCI_WAVE_STATUS_BLOCKALIGN
,_MCISTR_int
);
620 ITEM1("level",MCI_WAVE_STATUS_LEVEL
,_MCISTR_int
);
623 FIXME(mci
,"unknown keyword '%s'\n",keywords
[i
]);
626 if (!statusParams
->dwItem
)
627 return MCIERR_MISSING_STRING_ARGUMENT
;
629 _MCI_CALL_DRIVER( MCI_STATUS
, SEGPTR_GET(statusParams
) );
631 _MCISTR_convreturn(type
,statusParams
->dwReturn
,lpstrReturnString
,uReturnLength
,uDevTyp
,timef
);
632 SEGPTR_FREE(statusParams
);
639 /* set specified parameters in respective MCI drivers
641 * "door open" eject media or somesuch
642 * "door close" load media
643 * "time format <timeformatname>" "ms" "milliseconds" "msf" "hmsf"
644 * "tmsf" "SMPTE 24" "SMPTE 25" "SMPTE 30"
646 * "audio [all|left|right] [on|off]" sets specified audiochannel on or off
647 * "video [on|off]" sets video on/off
649 * "formattag pcm" sets format to pcm
650 * "formattag <nr>" sets integer formattag value
651 * "any input" accept input from any known source
652 * "any output" output to any known destination
653 * "input <nr>" input from source <nr>
654 * "output <nr>" output to destination <nr>
655 * "channels <nr>" sets nr of channels
656 * "bytespersec <nr>" sets average bytes per second
657 * "samplespersec <nr>" sets average samples per second (1 sample can
659 * "alignment <nr>" sets the blockalignment to <nr>
660 * "bitspersample <nr>" sets the nr of bits per sample
662 * "master [midi|file|smpte|none]" sets the midi master device
663 * "slave [midi|file|smpte|none]" sets the midi master device
664 * "port mapper" midioutput to portmapper
665 * "port <nr>" midioutput to specified port
666 * "tempo <nr>" tempo of track (depends on timeformat/divtype)
667 * "offset <nr>" start offset?
670 MCISTR_Set(_MCISTR_PROTO_
) {
672 MCI_SET_PARMS setParams
;
673 MCI_WAVE_SET_PARMS16 wavesetParams
;
674 MCI_SEQ_SET_PARMS seqsetParams
;
676 union U
*pU
= SEGPTR_NEW(union U
);
679 pU
->setParams
.dwCallback
= hwndCallback
;
681 while (i
<nrofkeywords
) {
682 FLAG2("door","open",MCI_SET_DOOR_OPEN
);
683 FLAG2("door","closed",MCI_SET_DOOR_CLOSED
);
685 if ( !STRCMP(keywords
[i
],"time") &&
686 (i
+2<nrofkeywords
) &&
687 !STRCMP(keywords
[i
+1],"format")
689 dwFlags
|= MCI_SET_TIME_FORMAT
;
691 /* FIXME:is this a shortcut for milliseconds or
692 * minutes:seconds? */
693 if (!STRCMP(keywords
[i
+2],"ms"))
694 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
696 if (!STRCMP(keywords
[i
+2],"milliseconds"))
697 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MILLISECONDS
;
698 if (!STRCMP(keywords
[i
+2],"msf"))
699 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_MSF
;
700 if (!STRCMP(keywords
[i
+2],"hms"))
701 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_HMS
;
702 if (!STRCMP(keywords
[i
+2],"frames"))
703 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_FRAMES
;
704 if (!STRCMP(keywords
[i
+2],"track"))
705 pU
->setParams
.dwTimeFormat
= MCI_VD_FORMAT_TRACK
;
706 if (!STRCMP(keywords
[i
+2],"bytes"))
707 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_BYTES
;
708 if (!STRCMP(keywords
[i
+2],"samples"))
709 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SAMPLES
;
710 if (!STRCMP(keywords
[i
+2],"tmsf"))
711 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_TMSF
;
712 if ( !STRCMP(keywords
[i
+2],"song") &&
713 (i
+3<nrofkeywords
) &&
714 !STRCMP(keywords
[i
+3],"pointer")
716 pU
->setParams
.dwTimeFormat
= MCI_SEQ_FORMAT_SONGPTR
;
717 if (!STRCMP(keywords
[i
+2],"smpte") && (i
+3<nrofkeywords
)) {
718 if (!STRCMP(keywords
[i
+3],"24"))
719 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_24
;
720 if (!STRCMP(keywords
[i
+3],"25"))
721 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_25
;
722 if (!STRCMP(keywords
[i
+3],"30"))
723 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30
;
724 if (!STRCMP(keywords
[i
+3],"drop") && (i
+4<nrofkeywords
) && !STRCMP(keywords
[i
+4],"30")) {
725 pU
->setParams
.dwTimeFormat
= MCI_FORMAT_SMPTE_30DROP
;
734 if (!STRCMP(keywords
[i
],"audio") && (i
+1<nrofkeywords
)) {
735 dwFlags
|= MCI_SET_AUDIO
;
736 if (!STRCMP(keywords
[i
+1],"all"))
737 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_ALL
;
738 if (!STRCMP(keywords
[i
+1],"left"))
739 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_LEFT
;
740 if (!STRCMP(keywords
[i
+1],"right"))
741 pU
->setParams
.dwAudio
= MCI_SET_AUDIO_RIGHT
;
745 FLAG1("video",MCI_SET_VIDEO
);
746 FLAG1("on",MCI_SET_ON
);
747 FLAG1("off",MCI_SET_OFF
);
749 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
750 FLAG2("any","input",MCI_WAVE_SET_ANYINPUT
);
751 FLAG2("any","output",MCI_WAVE_SET_ANYOUTPUT
);
753 if ( !STRCMP(keywords
[i
],"formattag") &&
754 (i
+1<nrofkeywords
) &&
755 !STRCMP(keywords
[i
+1],"pcm")
757 dwFlags
|= MCI_WAVE_SET_FORMATTAG
;
758 pU
->wavesetParams
.wFormatTag
= WAVE_FORMAT_PCM
;
763 /* <keyword> <integer> */
764 #define WII(str,flag,fmt,element) \
765 if (!STRCMP(keywords[i],str) && (i+1<nrofkeywords)) {\
766 sscanf(keywords[i+1],fmt,&(pU->wavesetParams. element ));\
771 WII("formattag",MCI_WAVE_SET_FORMATTAG
,"%hu",wFormatTag
);
772 WII("channels",MCI_WAVE_SET_CHANNELS
,"%hu",nChannels
);
773 WII("bytespersec",MCI_WAVE_SET_AVGBYTESPERSEC
,"%lu",nAvgBytesPerSec
);
774 WII("samplespersec",MCI_WAVE_SET_SAMPLESPERSEC
,"%lu",nSamplesPerSec
);
775 WII("alignment",MCI_WAVE_SET_BLOCKALIGN
,"%hu",nBlockAlign
);
776 WII("bitspersample",MCI_WAVE_SET_BITSPERSAMPLE
,"%hu",wBitsPerSample
);
777 WII("input",MCI_WAVE_INPUT
,"%hu",wInput
);
778 WII("output",MCI_WAVE_OUTPUT
,"%hu",wOutput
);
781 case MCI_DEVTYPE_SEQUENCER
:
782 if (!STRCMP(keywords
[i
],"master") && (i
+1<nrofkeywords
)) {
783 dwFlags
|= MCI_SEQ_SET_MASTER
;
784 if (!STRCMP(keywords
[i
+1],"midi"))
785 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
786 if (!STRCMP(keywords
[i
+1],"file"))
787 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
788 if (!STRCMP(keywords
[i
+1],"smpte"))
789 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
790 if (!STRCMP(keywords
[i
+1],"none"))
791 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
795 if (!STRCMP(keywords
[i
],"slave") && (i
+1<nrofkeywords
)) {
796 dwFlags
|= MCI_SEQ_SET_SLAVE
;
797 if (!STRCMP(keywords
[i
+1],"midi"))
798 pU
->seqsetParams
.dwMaster
= MCI_SEQ_MIDI
;
799 if (!STRCMP(keywords
[i
+1],"file"))
800 pU
->seqsetParams
.dwMaster
= MCI_SEQ_FILE
;
801 if (!STRCMP(keywords
[i
+1],"smpte"))
802 pU
->seqsetParams
.dwMaster
= MCI_SEQ_SMPTE
;
803 if (!STRCMP(keywords
[i
+1],"none"))
804 pU
->seqsetParams
.dwMaster
= MCI_SEQ_NONE
;
808 if ( !STRCMP(keywords
[i
],"port") &&
809 (i
+1<nrofkeywords
) &&
810 !STRCMP(keywords
[i
+1],"mapper")
812 pU
->seqsetParams
.dwPort
=-1;/* FIXME:not sure*/
813 dwFlags
|= MCI_SEQ_SET_PORT
;
817 #define SII(str,flag,element) \
818 if (!STRCMP(keywords[i],str) && (i+1<nrofkeywords)) {\
819 sscanf(keywords[i+1],"%ld",&(pU->seqsetParams. element ));\
824 SII("tempo",MCI_SEQ_SET_TEMPO
,dwTempo
);
825 SII("port",MCI_SEQ_SET_PORT
,dwPort
);
826 SII("offset",MCI_SEQ_SET_PORT
,dwOffset
);
831 return MCIERR_MISSING_STRING_ARGUMENT
;
832 _MCI_CALL_DRIVER( MCI_SET
, SEGPTR_GET(pU
) );
839 * "off" disable break
840 * "on <keyid>" enable break on key with keyid
841 * (I strongly suspect, that there is another parameter:
843 * but I don't see it mentioned in my documentation.
847 MCISTR_Break(_MCISTR_PROTO_
)
849 MCI_BREAK_PARMS16
*breakParams
= SEGPTR_NEW(MCI_BREAK_PARMS16
);
852 if (!breakParams
) return 0;
853 /*breakParams.hwndBreak ? */
854 for (i
= 0; i
< nrofkeywords
; i
++)
856 FLAG1("off",MCI_BREAK_OFF
);
857 if (!strcmp(keywords
[i
],"on") && (nrofkeywords
>i
+1)) {
858 dwFlags
&=~MCI_BREAK_OFF
;
859 dwFlags
|=MCI_BREAK_KEY
;
860 sscanf(keywords
[i
+1],"%hd",&(breakParams
->nVirtKey
));
865 _MCI_CALL_DRIVER( MCI_BREAK
, SEGPTR_GET(breakParams
) );
866 SEGPTR_FREE(breakParams
);
870 #define ITEM1(str,item,xtype) \
871 if (!STRCMP(keywords[i],str)) {\
872 gdcParams->dwItem = item;\
877 #define ITEM2(str1,str2,item,xtype) \
878 if ( !STRCMP(keywords[i],str1) &&\
879 (i+1<nrofkeywords) &&\
880 !STRCMP(keywords[i+1],str2)\
882 gdcParams->dwItem = item;\
887 #define ITEM3(str1,str2,str3,item,xtype) \
888 if ( !STRCMP(keywords[i],str1) &&\
889 (i+2<nrofkeywords) &&\
890 !STRCMP(keywords[i+1],str2) &&\
891 !STRCMP(keywords[i+2],str3)\
893 gdcParams->dwItem = item;\
898 /* get device capabilities of MCI drivers
901 * "device type" returns device name as string
902 * "has audio" returns bool
903 * "has video" returns bool
904 * "uses files" returns bool
905 * "compound device" returns bool
906 * "can record" returns bool
907 * "can play" returns bool
908 * "can eject" returns bool
909 * "can save" returns bool
911 * "palettes" returns nr of available palette entries
912 * "windows" returns nr of available windows
913 * "can reverse" returns bool
914 * "can stretch" returns bool
915 * "slow play rate" returns the slow playrate
916 * "fast play rate" returns the fast playrate
917 * "normal play rate" returns the normal playrate
919 * "windows" returns nr of available windows
920 * "can stretch" returns bool
921 * "can freeze" returns bool
923 * "cav" assume CAV discs (default if no disk inserted)
924 * "clv" assume CLV discs
925 * "can reverse" returns bool
926 * "slow play rate" returns the slow playrate
927 * "fast play rate" returns the fast playrate
928 * "normal play rate" returns the normal playrate
930 * "inputs" returns nr of inputdevices
931 * "outputs" returns nr of outputdevices
934 MCISTR_Capability(_MCISTR_PROTO_
) {
935 MCI_GETDEVCAPS_PARMS
*gdcParams
= SEGPTR_NEW(MCI_GETDEVCAPS_PARMS
);
938 gdcParams
->dwCallback
= hwndCallback
;
940 return MCIERR_MISSING_STRING_ARGUMENT
;
941 /* well , thats default */
942 dwFlags
|= MCI_GETDEVCAPS_ITEM
;
943 gdcParams
->dwItem
= 0;
945 while (i
<nrofkeywords
) {
946 ITEM2("device","type",MCI_GETDEVCAPS_DEVICE_TYPE
,_MCISTR_devtype
);
947 ITEM2("has","audio",MCI_GETDEVCAPS_HAS_AUDIO
,_MCISTR_bool
);
948 ITEM2("has","video",MCI_GETDEVCAPS_HAS_VIDEO
,_MCISTR_bool
);
949 ITEM2("uses","files",MCI_GETDEVCAPS_USES_FILES
,_MCISTR_bool
);
950 ITEM2("compound","device",MCI_GETDEVCAPS_COMPOUND_DEVICE
,_MCISTR_bool
);
951 ITEM2("can","record",MCI_GETDEVCAPS_CAN_RECORD
,_MCISTR_bool
);
952 ITEM2("can","play",MCI_GETDEVCAPS_CAN_PLAY
,_MCISTR_bool
);
953 ITEM2("can","eject",MCI_GETDEVCAPS_CAN_EJECT
,_MCISTR_bool
);
954 ITEM2("can","save",MCI_GETDEVCAPS_CAN_SAVE
,_MCISTR_bool
);
956 case MCI_DEVTYPE_ANIMATION
:
957 ITEM1("palettes",MCI_ANIM_GETDEVCAPS_PALETTES
,_MCISTR_int
);
958 ITEM1("windows",MCI_ANIM_GETDEVCAPS_MAX_WINDOWS
,_MCISTR_int
);
959 ITEM2("can","reverse",MCI_ANIM_GETDEVCAPS_CAN_REVERSE
,_MCISTR_bool
);
960 ITEM2("can","stretch",MCI_ANIM_GETDEVCAPS_CAN_STRETCH
,_MCISTR_bool
);
961 ITEM3("slow","play","rate",MCI_ANIM_GETDEVCAPS_SLOW_RATE
,_MCISTR_int
);
962 ITEM3("fast","play","rate",MCI_ANIM_GETDEVCAPS_FAST_RATE
,_MCISTR_int
);
963 ITEM3("normal","play","rate",MCI_ANIM_GETDEVCAPS_NORMAL_RATE
,_MCISTR_int
);
965 case MCI_DEVTYPE_OVERLAY
:
966 ITEM1("windows",MCI_OVLY_GETDEVCAPS_MAX_WINDOWS
,_MCISTR_int
);
967 ITEM2("can","freeze",MCI_OVLY_GETDEVCAPS_CAN_FREEZE
,_MCISTR_bool
);
968 ITEM2("can","stretch",MCI_OVLY_GETDEVCAPS_CAN_STRETCH
,_MCISTR_bool
);
970 case MCI_DEVTYPE_VIDEODISC
:
971 FLAG1("cav",MCI_VD_GETDEVCAPS_CAV
);
972 FLAG1("clv",MCI_VD_GETDEVCAPS_CLV
);
973 ITEM2("can","reverse",MCI_VD_GETDEVCAPS_CAN_REVERSE
,_MCISTR_bool
);
974 ITEM3("slow","play","rate",MCI_VD_GETDEVCAPS_SLOW_RATE
,_MCISTR_int
);
975 ITEM3("fast","play","rate",MCI_VD_GETDEVCAPS_FAST_RATE
,_MCISTR_int
);
976 ITEM3("normal","play","rate",MCI_VD_GETDEVCAPS_NORMAL_RATE
,_MCISTR_int
);
978 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
979 ITEM1("inputs",MCI_WAVE_GETDEVCAPS_INPUTS
,_MCISTR_int
);
980 ITEM1("outputs",MCI_WAVE_GETDEVCAPS_OUTPUTS
,_MCISTR_int
);
985 _MCI_CALL_DRIVER( MCI_GETDEVCAPS
, SEGPTR_GET(gdcParams
) );
986 /* no timeformat needed */
988 _MCISTR_convreturn( type
, gdcParams
->dwReturn
, lpstrReturnString
,
989 uReturnLength
, uDevTyp
, 0 );
990 SEGPTR_FREE(gdcParams
);
996 /* resumes operation of device. no arguments, no return values */
998 MCISTR_Resume(_MCISTR_PROTO_
)
1000 MCI_GENERIC_PARMS
*genParams
= SEGPTR_NEW(MCI_GENERIC_PARMS
);
1002 genParams
->dwCallback
= hwndCallback
;
1003 _MCI_CALL_DRIVER( MCI_RESUME
, SEGPTR_GET(genParams
) );
1007 /* pauses operation of device. no arguments, no return values */
1009 MCISTR_Pause(_MCISTR_PROTO_
)
1011 MCI_GENERIC_PARMS
*genParams
= SEGPTR_NEW(MCI_GENERIC_PARMS
);
1013 genParams
->dwCallback
= hwndCallback
;
1014 _MCI_CALL_DRIVER( MCI_PAUSE
, SEGPTR_GET(genParams
) );
1018 /* stops operation of device. no arguments, no return values */
1020 MCISTR_Stop(_MCISTR_PROTO_
)
1022 MCI_GENERIC_PARMS
*genParams
= SEGPTR_NEW(MCI_GENERIC_PARMS
);
1024 genParams
->dwCallback
= hwndCallback
;
1025 _MCI_CALL_DRIVER( MCI_STOP
, SEGPTR_GET(genParams
) );
1029 /* starts recording.
1031 * "overwrite" overwrite existing things
1032 * "insert" insert at current position
1033 * "to <time>" record up to <time> (specified in timeformat)
1034 * "from <time>" record from <time> (specified in timeformat)
1037 MCISTR_Record(_MCISTR_PROTO_
) {
1038 int i
,res
,timef
,nrargs
,j
,k
,a
[4];
1040 MCI_RECORD_PARMS
*recordParams
= SEGPTR_NEW(MCI_RECORD_PARMS
);
1042 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
1043 if (res
) return res
;
1046 case MCI_FORMAT_MILLISECONDS
:
1047 case MCI_FORMAT_FRAMES
:
1048 case MCI_FORMAT_BYTES
:
1049 case MCI_FORMAT_SAMPLES
:
1053 case MCI_FORMAT_HMS
:
1054 case MCI_FORMAT_MSF
:
1055 parsestr
="%d:%d:%d";
1058 case MCI_FORMAT_TMSF
:
1059 parsestr
="%d:%d:%d:%d";
1062 default:FIXME(mci
,"unknown timeformat %d, please report.\n",timef
);
1067 recordParams
->dwCallback
= hwndCallback
;
1069 while (i
<nrofkeywords
) {
1070 if (!strcmp(keywords
[i
],"to") && (i
+1<nrofkeywords
)) {
1072 a
[0]=a
[1]=a
[2]=a
[3]=0;
1073 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1074 /* add up all integers we got, if we have more
1075 * shift them. (Well I should use the macros in
1076 * mmsystem.h, right).
1078 recordParams
->dwTo
=0;
1080 recordParams
->dwTo
+=a
[k
]<<(8*(nrargs
-k
));
1084 if (!strcmp(keywords
[i
],"from") && (i
+1<nrofkeywords
)) {
1085 dwFlags
|= MCI_FROM
;
1086 a
[0]=a
[1]=a
[2]=a
[3]=0;
1087 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1089 recordParams
->dwFrom
=0;
1091 recordParams
->dwFrom
+=a
[k
]<<(8*(nrargs
-k
));
1095 FLAG1("insert",MCI_RECORD_INSERT
);
1096 FLAG1("overwrite",MCI_RECORD_OVERWRITE
);
1099 _MCI_CALL_DRIVER( MCI_RECORD
, SEGPTR_GET(recordParams
) );
1100 SEGPTR_FREE(recordParams
);
1106 * "to <time>" play up to <time> (specified in set timeformat)
1107 * "from <time>" play from <time> (specified in set timeformat)
1111 * "scan" play as fast as possible (with audio disabled perhaps)
1112 * "reverse" play reverse
1113 * "speed <fps>" play with specified frames per second
1117 * "scan" play as fast as possible (with audio disabled perhaps)
1118 * "reverse" play reverse
1119 * "speed <fps>" play with specified frames per second
1122 MCISTR_Play(_MCISTR_PROTO_
) {
1123 int i
,res
,timef
,nrargs
,j
,k
,a
[4];
1126 MCI_PLAY_PARMS playParams
;
1127 MCI_VD_PLAY_PARMS vdplayParams
;
1128 MCI_ANIM_PLAY_PARMS animplayParams
;
1130 union U
*pU
= SEGPTR_NEW(union U
);
1132 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
1133 if (res
) return res
;
1135 case MCI_FORMAT_MILLISECONDS
:
1136 case MCI_FORMAT_FRAMES
:
1137 case MCI_FORMAT_BYTES
:
1138 case MCI_FORMAT_SAMPLES
:
1142 case MCI_FORMAT_HMS
:
1143 case MCI_FORMAT_MSF
:
1144 parsestr
="%d:%d:%d";
1147 case MCI_FORMAT_TMSF
:
1148 parsestr
="%d:%d:%d:%d";
1151 default:FIXME(mci
,"unknown timeformat %d, please report.\n",timef
);
1156 pU
->playParams
.dwCallback
=hwndCallback
;
1158 while (i
<nrofkeywords
) {
1159 if (!strcmp(keywords
[i
],"to") && (i
+1<nrofkeywords
)) {
1161 a
[0]=a
[1]=a
[2]=a
[3]=0;
1162 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1163 /* add up all integers we got, if we have more
1164 * shift them. (Well I should use the macros in
1165 * mmsystem.h, right).
1167 pU
->playParams
.dwTo
=0;
1169 pU
->playParams
.dwTo
+=a
[k
]<<(8*(nrargs
-k
));
1173 if (!strcmp(keywords
[i
],"from") && (i
+1<nrofkeywords
)) {
1174 dwFlags
|= MCI_FROM
;
1175 a
[0]=a
[1]=a
[2]=a
[3]=0;
1176 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1178 pU
->playParams
.dwFrom
=0;
1180 pU
->playParams
.dwFrom
+=a
[k
]<<(8*(nrargs
-k
));
1185 case MCI_DEVTYPE_VIDEODISC
:
1186 FLAG1("slow",MCI_VD_PLAY_SLOW
);
1187 FLAG1("fast",MCI_VD_PLAY_FAST
);
1188 FLAG1("scan",MCI_VD_PLAY_SCAN
);
1189 FLAG1("reverse",MCI_VD_PLAY_REVERSE
);
1190 if (!STRCMP(keywords
[i
],"speed") && (i
+1<nrofkeywords
)) {
1191 dwFlags
|= MCI_VD_PLAY_SPEED
;
1192 sscanf(keywords
[i
+1],"%ld",&(pU
->vdplayParams
.dwSpeed
));
1197 case MCI_DEVTYPE_ANIMATION
:
1198 FLAG1("slow",MCI_ANIM_PLAY_SLOW
);
1199 FLAG1("fast",MCI_ANIM_PLAY_FAST
);
1200 FLAG1("scan",MCI_ANIM_PLAY_SCAN
);
1201 FLAG1("reverse",MCI_ANIM_PLAY_REVERSE
);
1202 if (!STRCMP(keywords
[i
],"speed") && (i
+1<nrofkeywords
)) {
1203 dwFlags
|= MCI_ANIM_PLAY_SPEED
;
1204 sscanf(keywords
[i
+1],"%ld",&(pU
->animplayParams
.dwSpeed
));
1212 _MCI_CALL_DRIVER( MCI_PLAY
, SEGPTR_GET(pU
) );
1217 /* seek to a specified position
1219 * "to start" seek to start of medium
1220 * "to end" seek to end of medium
1221 * "to <time>" seek to <time> specified in current timeformat
1224 MCISTR_Seek(_MCISTR_PROTO_
) {
1225 int i
,res
,timef
,nrargs
,j
,k
,a
[4];
1227 MCI_SEEK_PARMS
*seekParams
= SEGPTR_NEW(MCI_SEEK_PARMS
);
1229 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
1230 if (res
) return res
;
1232 case MCI_FORMAT_MILLISECONDS
:
1233 case MCI_FORMAT_FRAMES
:
1234 case MCI_FORMAT_BYTES
:
1235 case MCI_FORMAT_SAMPLES
:
1239 case MCI_FORMAT_HMS
:
1240 case MCI_FORMAT_MSF
:
1241 parsestr
="%d:%d:%d";
1244 case MCI_FORMAT_TMSF
:
1245 parsestr
="%d:%d:%d:%d";
1248 default:FIXME(mci
,"unknown timeformat %d, please report.\n",timef
);
1253 seekParams
->dwCallback
=hwndCallback
;
1255 while (i
<nrofkeywords
) {
1256 if ( !STRCMP(keywords
[i
],"to") && (i
+1<nrofkeywords
)) {
1257 if (!STRCMP(keywords
[i
+1],"start")) {
1258 dwFlags
|=MCI_SEEK_TO_START
;
1263 if (!STRCMP(keywords
[i
+1],"end")) {
1264 dwFlags
|=MCI_SEEK_TO_END
;
1271 a
[0]=a
[1]=a
[2]=a
[3]=0;
1272 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1275 seekParams
->dwTo
+=a
[k
]<<(8*(nrargs
-k
));
1279 case MCI_DEVTYPE_VIDEODISC
:
1280 FLAG1("reverse",MCI_VD_SEEK_REVERSE
);
1285 _MCI_CALL_DRIVER( MCI_SEEK
, SEGPTR_GET(seekParams
) );
1286 SEGPTR_FREE(seekParams
);
1290 /* close media/driver */
1292 MCISTR_Close(_MCISTR_PROTO_
)
1294 MCI_GENERIC_PARMS
*closeParams
= SEGPTR_NEW(MCI_GENERIC_PARMS
);
1296 _MCI_CALL_DRIVER( MCI_CLOSE
, SEGPTR_GET(closeParams
) );
1297 SEGPTR_FREE(closeParams
);
1301 /* return information.
1303 * "product" return product name (human readable)
1304 * "file" return filename
1306 * "text" returns text?
1308 * "text" returns text?
1311 MCISTR_Info(_MCISTR_PROTO_
)
1313 MCI_INFO_PARMS16
*infoParams
= SEGPTR_NEW(MCI_INFO_PARMS16
);
1318 i
=0;while (i
<nrofkeywords
) {
1319 FLAG1("product",MCI_INFO_PRODUCT
);
1320 FLAG1("file",MCI_INFO_FILE
);
1322 case MCI_DEVTYPE_ANIMATION
:
1323 FLAG1("text",MCI_ANIM_INFO_TEXT
);
1325 case MCI_DEVTYPE_OVERLAY
:
1326 FLAG1("text",MCI_OVLY_INFO_TEXT
);
1331 if (dwFlags
== sflags
)
1332 return MCIERR_MISSING_STRING_ARGUMENT
;
1333 /* MCI driver will fill in lpstrReturn, dwRetSize.
1334 * FIXME: I don't know if this is correct behaviour
1336 _MCI_CALL_DRIVER( MCI_INFO
, SEGPTR_GET(infoParams
) );
1338 _MCI_STR(infoParams
->lpstrReturn
);
1339 SEGPTR_FREE(infoParams
);
1343 DWORD
mciSysInfo(DWORD dwFlags
,LPMCI_SYSINFO_PARMS16 lpParms
);
1345 /* query MCI driver itself for information
1347 * "installname" return install name of <device> (system.ini)
1348 * "quantity" return nr of installed drivers
1349 * "open" open drivers only (additional flag)
1350 * "name <nr>" return nr of devices with <devicetyp>
1351 * "name all" return nr of all devices
1353 * FIXME: mciSysInfo() is broken I think.
1356 MCISTR_Sysinfo(_MCISTR_PROTO_
) {
1357 MCI_SYSINFO_PARMS16 sysinfoParams
;
1360 sysinfoParams
.lpstrReturn
= lpstrReturnString
;
1361 sysinfoParams
.dwRetSize
= uReturnLength
;
1362 sysinfoParams
.wDeviceType
= uDevTyp
;
1364 while (i
<nrofkeywords
) {
1365 FLAG1("installname",MCI_SYSINFO_INSTALLNAME
);
1366 FLAG1("quantity",MCI_SYSINFO_INSTALLNAME
);
1367 FLAG1("open",MCI_SYSINFO_OPEN
);
1368 if (!strcmp(keywords
[i
],"name") && (i
+1<nrofkeywords
)) {
1369 sscanf(keywords
[i
+1],"%ld",&(sysinfoParams
.dwNumber
));
1370 dwFlags
|= MCI_SYSINFO_NAME
;
1376 res
=mciSysInfo(dwFlags
,&sysinfoParams
);
1377 if (dwFlags
& MCI_SYSINFO_QUANTITY
) {
1380 sprintf(buf
,"%ld",*(long*)PTR_SEG_TO_LIN(lpstrReturnString
));
1383 /* no need to copy anything back, mciSysInfo did it for us */
1388 * Argument: "<filename>"
1389 * Overlay: "at <left> <top> <right> <bottom>" additional
1392 MCISTR_Load(_MCISTR_PROTO_
) {
1394 MCI_LOAD_PARMS16 loadParams
;
1395 MCI_OVLY_LOAD_PARMS16 ovlyloadParams
;
1397 union U
*pU
= SEGPTR_NEW(union U
);
1402 while (i
<nrofkeywords
) {
1404 case MCI_DEVTYPE_OVERLAY
:
1405 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1406 dwFlags
|= MCI_OVLY_RECT
;
1407 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlyloadParams
.rc
.left
));
1408 sscanf(keywords
[i
+2],"%hd",&(pU
->ovlyloadParams
.rc
.top
));
1409 sscanf(keywords
[i
+3],"%hd",&(pU
->ovlyloadParams
.rc
.right
));
1410 sscanf(keywords
[i
+4],"%hd",&(pU
->ovlyloadParams
.rc
.bottom
));
1411 memcpy(keywords
+i
,keywords
+(i
+5),nrofkeywords
-(i
+5));
1416 len
+=strlen(keywords
[i
])+1;
1419 s
=(char*)SEGPTR_ALLOC(len
);
1421 while (i
<nrofkeywords
) {
1422 strcat(s
,keywords
[i
]);
1424 if (i
<nrofkeywords
) strcat(s
," ");
1426 pU
->loadParams
.lpfilename
=(LPSTR
)SEGPTR_GET(s
);
1427 dwFlags
|= MCI_LOAD_FILE
;
1428 _MCI_CALL_DRIVER( MCI_LOAD
, SEGPTR_GET(pU
) );
1435 * Argument: "<filename>"
1436 * Overlay: "at <left> <top> <right> <bottom>" additional
1439 MCISTR_Save(_MCISTR_PROTO_
) {
1441 MCI_SAVE_PARMS saveParams
;
1442 MCI_OVLY_SAVE_PARMS16 ovlysaveParams
;
1444 union U
*pU
= SEGPTR_NEW(union U
);
1449 while (i
<nrofkeywords
) {
1451 case MCI_DEVTYPE_OVERLAY
:
1452 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1453 dwFlags
|= MCI_OVLY_RECT
;
1454 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlysaveParams
.rc
.left
));
1455 sscanf(keywords
[i
+2],"%hd",&(pU
->ovlysaveParams
.rc
.top
));
1456 sscanf(keywords
[i
+3],"%hd",&(pU
->ovlysaveParams
.rc
.right
));
1457 sscanf(keywords
[i
+4],"%hd",&(pU
->ovlysaveParams
.rc
.bottom
));
1458 memcpy(keywords
+i
,keywords
+(i
+5),nrofkeywords
-(i
+5));
1463 len
+=strlen(keywords
[i
])+1;
1466 s
=(char*)SEGPTR_ALLOC(len
);
1468 while (i
<nrofkeywords
) {
1469 strcat(s
,keywords
[i
]);
1471 if (i
<nrofkeywords
) strcat(s
," ");
1473 pU
->saveParams
.lpfilename
=(LPSTR
)SEGPTR_GET(s
);
1474 dwFlags
|= MCI_LOAD_FILE
;
1475 _MCI_CALL_DRIVER( MCI_SAVE
, SEGPTR_GET(pU
) );
1481 /* prepare device for input/output
1482 * (only applyable to waveform audio)
1485 MCISTR_Cue(_MCISTR_PROTO_
) {
1486 MCI_GENERIC_PARMS
*cueParams
= SEGPTR_NEW(MCI_GENERIC_PARMS
);
1490 while (i
<nrofkeywords
) {
1492 case MCI_DEVTYPE_WAVEFORM_AUDIO
:
1493 FLAG1("input",MCI_WAVE_INPUT
);
1494 FLAG1("output",MCI_WAVE_OUTPUT
);
1499 _MCI_CALL_DRIVER( MCI_CUE
, SEGPTR_GET(cueParams
) );
1500 SEGPTR_FREE(cueParams
);
1504 /* delete information */
1506 MCISTR_Delete(_MCISTR_PROTO_
) {
1507 int timef
,nrargs
,i
,j
,k
,a
[4],res
;
1509 MCI_WAVE_DELETE_PARMS
*deleteParams
= SEGPTR_NEW(MCI_WAVE_DELETE_PARMS
);
1511 /* only implemented for waveform audio */
1512 if (uDevTyp
!= MCI_DEVTYPE_WAVEFORM_AUDIO
)
1513 return MCIERR_UNSUPPORTED_FUNCTION
; /* well it fits */
1514 res
= _MCISTR_determine_timeformat(dev
,wDevID
,uDevTyp
,&timef
);
1515 if (res
) return res
;
1517 case MCI_FORMAT_MILLISECONDS
:
1518 case MCI_FORMAT_FRAMES
:
1519 case MCI_FORMAT_BYTES
:
1520 case MCI_FORMAT_SAMPLES
:
1524 case MCI_FORMAT_HMS
:
1525 case MCI_FORMAT_MSF
:
1526 parsestr
="%d:%d:%d";
1529 case MCI_FORMAT_TMSF
:
1530 parsestr
="%d:%d:%d:%d";
1533 default:FIXME(mci
,"unknown timeformat %d, please report.\n",timef
);
1539 while (i
<nrofkeywords
) {
1540 if (!strcmp(keywords
[i
],"to") && (i
+1<nrofkeywords
)) {
1542 a
[0]=a
[1]=a
[2]=a
[3]=0;
1543 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1544 /* add up all integers we got, if we have more
1545 * shift them. (Well I should use the macros in
1546 * mmsystem.h, right).
1548 deleteParams
->dwTo
=0;
1550 deleteParams
->dwTo
+=a
[k
]<<(8*(nrargs
-k
));
1554 if (!strcmp(keywords
[i
],"from") && (i
+1<nrofkeywords
)) {
1555 dwFlags
|= MCI_FROM
;
1556 a
[0]=a
[1]=a
[2]=a
[3]=0;
1557 j
=sscanf(keywords
[i
+1],parsestr
,&a
[0],&a
[1],&a
[2],&a
[3]);
1559 deleteParams
->dwFrom
=0;
1561 deleteParams
->dwFrom
+=a
[k
]<<(8*(nrargs
-k
));
1567 _MCI_CALL_DRIVER( MCI_DELETE
, SEGPTR_GET(deleteParams
) );
1568 SEGPTR_FREE(deleteParams
);
1572 /* send command to device. only applies to videodisc */
1574 MCISTR_Escape(_MCISTR_PROTO_
)
1576 MCI_VD_ESCAPE_PARMS16
*escapeParams
= SEGPTR_NEW(MCI_VD_ESCAPE_PARMS16
);
1580 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
1581 return MCIERR_UNSUPPORTED_FUNCTION
;
1583 while (i
<nrofkeywords
) {
1584 len
+=strlen(keywords
[i
])+1;
1587 s
=(char*)SEGPTR_ALLOC(len
);
1589 while (i
<nrofkeywords
) {
1590 strcat(s
,keywords
[i
]);
1592 if (i
<nrofkeywords
) strcat(s
," ");
1594 escapeParams
->lpstrCommand
= (LPSTR
)SEGPTR_GET(s
);
1595 dwFlags
|= MCI_VD_ESCAPE_STRING
;
1596 _MCI_CALL_DRIVER( MCI_ESCAPE
, SEGPTR_GET(escapeParams
) );
1598 SEGPTR_FREE(escapeParams
);
1602 /* unfreeze [part of] the overlayed video
1603 * only applyable to Overlay devices
1606 MCISTR_Unfreeze(_MCISTR_PROTO_
)
1608 MCI_OVLY_RECT_PARMS16
*unfreezeParams
= SEGPTR_NEW(MCI_OVLY_RECT_PARMS16
);
1611 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1612 return MCIERR_UNSUPPORTED_FUNCTION
;
1613 i
=0;while (i
<nrofkeywords
) {
1614 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1615 sscanf(keywords
[i
+1],"%hd",&(unfreezeParams
->rc
.left
));
1616 sscanf(keywords
[i
+2],"%hd",&(unfreezeParams
->rc
.top
));
1617 sscanf(keywords
[i
+3],"%hd",&(unfreezeParams
->rc
.right
));
1618 sscanf(keywords
[i
+4],"%hd",&(unfreezeParams
->rc
.bottom
));
1619 dwFlags
|= MCI_OVLY_RECT
;
1625 _MCI_CALL_DRIVER( MCI_UNFREEZE
, SEGPTR_GET(unfreezeParams
) );
1626 SEGPTR_FREE(unfreezeParams
);
1629 /* freeze [part of] the overlayed video
1630 * only applyable to Overlay devices
1633 MCISTR_Freeze(_MCISTR_PROTO_
)
1635 MCI_OVLY_RECT_PARMS16
*freezeParams
= SEGPTR_NEW(MCI_OVLY_RECT_PARMS16
);
1638 if (uDevTyp
!= MCI_DEVTYPE_OVERLAY
)
1639 return MCIERR_UNSUPPORTED_FUNCTION
;
1640 i
=0;while (i
<nrofkeywords
) {
1641 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1642 sscanf(keywords
[i
+1],"%hd",&(freezeParams
->rc
.left
));
1643 sscanf(keywords
[i
+2],"%hd",&(freezeParams
->rc
.top
));
1644 sscanf(keywords
[i
+3],"%hd",&(freezeParams
->rc
.right
));
1645 sscanf(keywords
[i
+4],"%hd",&(freezeParams
->rc
.bottom
));
1646 dwFlags
|= MCI_OVLY_RECT
;
1652 _MCI_CALL_DRIVER( MCI_FREEZE
, SEGPTR_GET(freezeParams
) );
1653 SEGPTR_FREE(freezeParams
);
1657 /* copy parts of image to somewhere else
1658 * "source [at <left> <top> <right> <bottom>]" source is framebuffer [or rect]
1659 * "destination [at <left> <top> <right> <bottom>]" destination is framebuffer [or rect]
1661 * "frame [at <left> <top> <right> <bottom>]" frame is framebuffer [or rect]
1662 * where the video input is placed
1663 * "video [at <left> <top> <right> <bottom>]" video is whole video [or rect]
1664 * (defining part of input to
1667 * FIXME: This whole junk is passing multiple rectangles.
1668 * I don't know how to do that with the present interface.
1669 * (Means code below is broken)
1672 MCISTR_Put(_MCISTR_PROTO_
) {
1674 MCI_OVLY_RECT_PARMS16 ovlyputParams
;
1675 MCI_ANIM_RECT_PARMS16 animputParams
;
1677 union U
*pU
= SEGPTR_NEW(union U
);
1679 i
=0;while (i
<nrofkeywords
) {
1681 case MCI_DEVTYPE_ANIMATION
:
1682 FLAG1("source",MCI_ANIM_PUT_SOURCE
);
1683 FLAG1("destination",MCI_ANIM_PUT_DESTINATION
);
1684 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1685 sscanf(keywords
[i
+1],"%hd",&(pU
->animputParams
.rc
.left
));
1686 sscanf(keywords
[i
+2],"%hd",&(pU
->animputParams
.rc
.top
));
1687 sscanf(keywords
[i
+3],"%hd",&(pU
->animputParams
.rc
.right
));
1688 sscanf(keywords
[i
+4],"%hd",&(pU
->animputParams
.rc
.bottom
));
1689 dwFlags
|= MCI_ANIM_RECT
;
1694 case MCI_DEVTYPE_OVERLAY
:
1695 FLAG1("source",MCI_OVLY_PUT_SOURCE
);
1696 FLAG1("destination",MCI_OVLY_PUT_DESTINATION
);
1697 FLAG1("video",MCI_OVLY_PUT_VIDEO
);
1698 FLAG1("frame",MCI_OVLY_PUT_FRAME
);
1699 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1700 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlyputParams
.rc
.left
));
1701 sscanf(keywords
[i
+2],"%hd",&(pU
->ovlyputParams
.rc
.top
));
1702 sscanf(keywords
[i
+3],"%hd",&(pU
->ovlyputParams
.rc
.right
));
1703 sscanf(keywords
[i
+4],"%hd",&(pU
->ovlyputParams
.rc
.bottom
));
1704 dwFlags
|= MCI_OVLY_RECT
;
1712 _MCI_CALL_DRIVER( MCI_PUT
, SEGPTR_GET(pU
) );
1717 /* palette behaviour changing
1719 * "normal" realize the palette normally
1720 * "background" realize the palette as background palette
1723 MCISTR_Realize(_MCISTR_PROTO_
)
1725 MCI_GENERIC_PARMS
*realizeParams
= SEGPTR_NEW(MCI_GENERIC_PARMS
);
1728 if (uDevTyp
!= MCI_DEVTYPE_ANIMATION
)
1729 return MCIERR_UNSUPPORTED_FUNCTION
;
1731 while (i
<nrofkeywords
) {
1732 FLAG1("background",MCI_ANIM_REALIZE_BKGD
);
1733 FLAG1("normal",MCI_ANIM_REALIZE_NORM
);
1736 _MCI_CALL_DRIVER( MCI_REALIZE
, SEGPTR_GET(realizeParams
) );
1737 SEGPTR_FREE(realizeParams
);
1741 /* videodisc spinning
1746 MCISTR_Spin(_MCISTR_PROTO_
)
1748 MCI_GENERIC_PARMS
*spinParams
= SEGPTR_NEW(MCI_GENERIC_PARMS
);
1751 if (uDevTyp
!= MCI_DEVTYPE_VIDEODISC
)
1752 return MCIERR_UNSUPPORTED_FUNCTION
;
1754 while (i
<nrofkeywords
) {
1755 FLAG1("up",MCI_VD_SPIN_UP
);
1756 FLAG1("down",MCI_VD_SPIN_UP
);
1759 _MCI_CALL_DRIVER( MCI_SPIN
, SEGPTR_GET(spinParams
) );
1760 SEGPTR_FREE(spinParams
);
1764 /* step single frames
1765 * "reverse" optional flag
1766 * "by <nr>" for <nr> frames
1769 MCISTR_Step(_MCISTR_PROTO_
) {
1771 MCI_ANIM_STEP_PARMS animstepParams
;
1772 MCI_VD_STEP_PARMS vdstepParams
;
1774 union U
*pU
= SEGPTR_NEW(union U
);
1778 while (i
<nrofkeywords
) {
1780 case MCI_DEVTYPE_ANIMATION
:
1781 FLAG1("reverse",MCI_ANIM_STEP_REVERSE
);
1782 if (!STRCMP(keywords
[i
],"by") && (i
+1<nrofkeywords
)) {
1783 sscanf(keywords
[i
+1],"%ld",&(pU
->animstepParams
.dwFrames
));
1784 dwFlags
|= MCI_ANIM_STEP_FRAMES
;
1789 case MCI_DEVTYPE_VIDEODISC
:
1790 FLAG1("reverse",MCI_VD_STEP_REVERSE
);
1791 if (!STRCMP(keywords
[i
],"by") && (i
+1<nrofkeywords
)) {
1792 sscanf(keywords
[i
+1],"%ld",&(pU
->vdstepParams
.dwFrames
));
1793 dwFlags
|= MCI_VD_STEP_FRAMES
;
1801 _MCI_CALL_DRIVER( MCI_STEP
, SEGPTR_GET(pU
) );
1806 /* update animation window
1808 * "at <left> <top> <right> <bottom>" only in this rectangle
1809 * "hdc" device context
1812 MCISTR_Update(_MCISTR_PROTO_
) {
1814 MCI_ANIM_UPDATE_PARMS16
*updateParams
= SEGPTR_NEW(MCI_ANIM_UPDATE_PARMS16
);
1817 while (i
<nrofkeywords
) {
1818 if (!STRCMP(keywords
[i
],"at") && (i
+4<nrofkeywords
)) {
1819 sscanf(keywords
[i
+1],"%hd",&(updateParams
->rc
.left
));
1820 sscanf(keywords
[i
+2],"%hd",&(updateParams
->rc
.top
));
1821 sscanf(keywords
[i
+3],"%hd",&(updateParams
->rc
.right
));
1822 sscanf(keywords
[i
+4],"%hd",&(updateParams
->rc
.bottom
));
1823 dwFlags
|= MCI_ANIM_RECT
;
1827 if (!STRCMP(keywords
[i
],"hdc") && (i
+1<nrofkeywords
)) {
1828 dwFlags
|= MCI_ANIM_UPDATE_HDC
;
1829 sscanf(keywords
[i
+1],"%hd",&(updateParams
->hDC
));
1835 _MCI_CALL_DRIVER( MCI_UPDATE
, SEGPTR_GET(updateParams
) );
1836 SEGPTR_FREE(updateParams
);
1840 /* where command for animation and overlay drivers.
1841 * just returns the specified rectangle as a string
1850 MCISTR_Where(_MCISTR_PROTO_
) {
1852 MCI_ANIM_RECT_PARMS16 animwhereParams
;
1853 MCI_OVLY_RECT_PARMS16 ovlywhereParams
;
1855 union U
*pU
= SEGPTR_NEW(union U
);
1859 while (i
<nrofkeywords
) {
1861 case MCI_DEVTYPE_ANIMATION
:
1862 FLAG1("source",MCI_ANIM_WHERE_SOURCE
);
1863 FLAG1("destination",MCI_ANIM_WHERE_DESTINATION
);
1865 case MCI_DEVTYPE_OVERLAY
:
1866 FLAG1("source",MCI_OVLY_WHERE_SOURCE
);
1867 FLAG1("destination",MCI_OVLY_WHERE_DESTINATION
);
1868 FLAG1("video",MCI_OVLY_WHERE_VIDEO
);
1869 FLAG1("frame",MCI_OVLY_WHERE_FRAME
);
1874 _MCI_CALL_DRIVER( MCI_WHERE
, SEGPTR_GET(pU
) );
1878 case MCI_DEVTYPE_ANIMATION
:
1879 sprintf(buf
,"%d %d %d %d",
1880 pU
->animwhereParams
.rc
.left
,
1881 pU
->animwhereParams
.rc
.top
,
1882 pU
->animwhereParams
.rc
.right
,
1883 pU
->animwhereParams
.rc
.bottom
1886 case MCI_DEVTYPE_OVERLAY
:
1887 sprintf(buf
,"%d %d %d %d",
1888 pU
->ovlywhereParams
.rc
.left
,
1889 pU
->ovlywhereParams
.rc
.top
,
1890 pU
->ovlywhereParams
.rc
.right
,
1891 pU
->ovlywhereParams
.rc
.bottom
1894 default:strcpy(buf
,"0 0 0 0");break;
1903 MCISTR_Window(_MCISTR_PROTO_
) {
1907 MCI_ANIM_WINDOW_PARMS16 animwindowParams
;
1908 MCI_OVLY_WINDOW_PARMS16 ovlywindowParams
;
1910 union U
*pU
= SEGPTR_NEW(union U
);
1914 while (i
<nrofkeywords
) {
1916 case MCI_DEVTYPE_ANIMATION
:
1917 if (!STRCMP(keywords
[i
],"handle") && (i
+1<nrofkeywords
)) {
1918 dwFlags
|= MCI_ANIM_WINDOW_HWND
;
1919 if (!STRCMP(keywords
[i
+1],"default"))
1920 pU
->animwindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
1922 sscanf(keywords
[i
+1],"%hd",&(pU
->animwindowParams
.hWnd
));
1926 if (!STRCMP(keywords
[i
],"state") && (i
+1<nrofkeywords
)) {
1927 dwFlags
|= MCI_ANIM_WINDOW_STATE
;
1928 if (!STRCMP(keywords
[i
+1],"hide"))
1929 pU
->animwindowParams
.nCmdShow
= SW_HIDE
;
1930 if (!STRCMP(keywords
[i
+1],"iconic"))
1931 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
1932 if (!STRCMP(keywords
[i
+1],"minimized"))
1933 pU
->animwindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
1934 if (!STRCMP(keywords
[i
+1],"maximized"))
1935 pU
->animwindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
1936 if (!STRCMP(keywords
[i
+1],"minimize"))
1937 pU
->animwindowParams
.nCmdShow
= SW_MINIMIZE
;
1938 if (!STRCMP(keywords
[i
+1],"normal"))
1939 pU
->animwindowParams
.nCmdShow
= SW_NORMAL
;
1940 if (!STRCMP(keywords
[i
+1],"show"))
1941 pU
->animwindowParams
.nCmdShow
= SW_SHOW
;
1942 if (!STRCMP(keywords
[i
+1],"no") && (i
+2<nrofkeywords
)) {
1943 if (!STRCMP(keywords
[i
+2],"active"))
1944 pU
->animwindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
1945 if (!STRCMP(keywords
[i
+2],"action"))
1946 pU
->animwindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
1952 /* text is enclosed in " ... " as it seems */
1953 if (!STRCMP(keywords
[i
],"text")) {
1957 if (keywords
[i
+1][0]!='"') {
1961 dwFlags
|= MCI_ANIM_WINDOW_TEXT
;
1962 len
= strlen(keywords
[i
+1])+1;
1964 while (j
<nrofkeywords
) {
1965 len
+= strlen(keywords
[j
])+1;
1966 if (strchr(keywords
[j
],'"'))
1970 s
=(char*)xmalloc(len
);
1971 strcpy(s
,keywords
[i
+1]+1);
1975 strcat(s
,keywords
[j
]);
1977 if ((t
=strchr(s
,'"'))) *t
='\0';
1978 /* FIXME: segmented pointer? */
1979 pU
->animwindowParams
.lpstrText
= s
;
1983 FLAG1("stretch",MCI_ANIM_WINDOW_ENABLE_STRETCH
);
1985 case MCI_DEVTYPE_OVERLAY
:
1986 if (!STRCMP(keywords
[i
],"handle") && (i
+1<nrofkeywords
)) {
1987 dwFlags
|= MCI_OVLY_WINDOW_HWND
;
1988 if (!STRCMP(keywords
[i
+1],"default"))
1989 pU
->ovlywindowParams
.hWnd
= MCI_OVLY_WINDOW_DEFAULT
;
1991 sscanf(keywords
[i
+1],"%hd",&(pU
->ovlywindowParams
.hWnd
));
1995 if (!STRCMP(keywords
[i
],"state") && (i
+1<nrofkeywords
)) {
1996 dwFlags
|= MCI_OVLY_WINDOW_STATE
;
1997 if (!STRCMP(keywords
[i
+1],"hide"))
1998 pU
->ovlywindowParams
.nCmdShow
= SW_HIDE
;
1999 if (!STRCMP(keywords
[i
+1],"iconic"))
2000 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINNOACTIVE
; /* correct? */
2001 if (!STRCMP(keywords
[i
+1],"minimized"))
2002 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMINIMIZED
;
2003 if (!STRCMP(keywords
[i
+1],"maximized"))
2004 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWMAXIMIZED
;
2005 if (!STRCMP(keywords
[i
+1],"minimize"))
2006 pU
->ovlywindowParams
.nCmdShow
= SW_MINIMIZE
;
2007 if (!STRCMP(keywords
[i
+1],"normal"))
2008 pU
->ovlywindowParams
.nCmdShow
= SW_NORMAL
;
2009 if (!STRCMP(keywords
[i
+1],"show"))
2010 pU
->ovlywindowParams
.nCmdShow
= SW_SHOW
;
2011 if (!STRCMP(keywords
[i
+1],"no") && (i
+2<nrofkeywords
)) {
2012 if (!STRCMP(keywords
[i
+2],"active"))
2013 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNOACTIVATE
;
2014 if (!STRCMP(keywords
[i
+2],"action"))
2015 pU
->ovlywindowParams
.nCmdShow
= SW_SHOWNA
;/* correct?*/
2021 /* text is enclosed in " ... " as it seems */
2022 if (!STRCMP(keywords
[i
],"text")) {
2026 if (keywords
[i
+1][0]!='"') {
2030 dwFlags
|= MCI_OVLY_WINDOW_TEXT
;
2031 len
= strlen(keywords
[i
+1])+1;
2033 while (j
<nrofkeywords
) {
2034 len
+= strlen(keywords
[j
])+1;
2035 if (strchr(keywords
[j
],'"'))
2039 s
=(char*)xmalloc(len
);
2040 strcpy(s
,keywords
[i
+1]+1);
2044 strcat(s
,keywords
[j
]);
2046 if ((t
=strchr(s
,'"'))) *t
='\0';
2047 /* FIXME: segmented pointer? */
2048 pU
->ovlywindowParams
.lpstrText
= s
;
2052 FLAG1("stretch",MCI_OVLY_WINDOW_ENABLE_STRETCH
);
2057 _MCI_CALL_DRIVER( MCI_WINDOW
, SEGPTR_GET(pU
) );
2063 struct _MCISTR_cmdtable
{
2065 DWORD (*fun
)(_MCISTR_PROTO_
);
2066 } MCISTR_cmdtable
[]={
2067 {"break", MCISTR_Break
},
2068 {"capability", MCISTR_Capability
},
2069 {"close", MCISTR_Close
},
2070 {"cue", MCISTR_Cue
},
2071 {"delete", MCISTR_Delete
},
2072 {"escape", MCISTR_Escape
},
2073 {"freeze", MCISTR_Freeze
},
2074 {"info", MCISTR_Info
},
2075 {"load", MCISTR_Load
},
2076 {"open", MCISTR_Open
},
2077 {"pause", MCISTR_Pause
},
2078 {"play", MCISTR_Play
},
2079 {"put", MCISTR_Put
},
2080 {"realize", MCISTR_Realize
},
2081 {"record", MCISTR_Record
},
2082 {"resume", MCISTR_Resume
},
2083 {"save", MCISTR_Save
},
2084 {"seek", MCISTR_Seek
},
2085 {"set", MCISTR_Set
},
2086 {"spin", MCISTR_Spin
},
2087 {"status", MCISTR_Status
},
2088 {"step", MCISTR_Step
},
2089 {"stop", MCISTR_Stop
},
2090 {"sysinfo", MCISTR_Sysinfo
},
2091 {"unfreeze", MCISTR_Unfreeze
},
2092 {"update", MCISTR_Update
},
2093 {"where", MCISTR_Where
},
2094 {"window", MCISTR_Window
},
2097 /**************************************************************************
2098 * mciSendString [MMSYSTEM.702]
2100 /* The usercode sends a string with a command (and flags) expressed in
2101 * words in it... We do our best to call aprobiate drivers,
2102 * and return a errorcode AND a readable string (if lpstrRS!=NULL)
2103 * Info gathered by watching cool134.exe and from Borland's mcistrwh.hlp
2105 /* FIXME: "all" is a valid devicetype and we should access all devices if
2106 * it is used. (imagine "close all"). Not implemented yet.
2108 DWORD WINAPI
mciSendString (LPCSTR lpstrCommand
, LPSTR lpstrReturnString
,
2109 UINT16 uReturnLength
, HWND16 hwndCallback
)
2111 char *cmd
,*dev
,*args
,**keywords
,*filename
;
2112 WORD uDevTyp
=0,wDevID
=0;
2114 int res
=0,i
,nrofkeywords
;
2116 TRACE(mci
,"('%s', %p, %d, %X)\n", lpstrCommand
,
2117 lpstrReturnString
, uReturnLength
, hwndCallback
2119 /* format is <command> <device> <optargs> */
2120 cmd
=strdup(lpstrCommand
);
2121 dev
=strchr(cmd
,' ');
2124 return MCIERR_MISSING_DEVICE_NAME
;
2127 args
=strchr(dev
,' ');
2128 if (args
!=NULL
) *args
++='\0';
2132 i
=1;/* nrofkeywords = nrofspaces+1 */
2134 while ((s
=strchr(s
,' '))!=NULL
) i
++,s
++;
2135 keywords
=(char**)xmalloc(sizeof(char*)*(i
+2));
2138 while (s
&& i
<nrofkeywords
) {
2146 keywords
=(char**)xmalloc(sizeof(char*));
2148 dwFlags
= 0; /* default flags */
2149 for (i
=0;i
<nrofkeywords
;) {
2150 /* take care, there is also a "device type" capability */
2151 if ((!STRCMP(keywords
[i
],"type")) && (i
<nrofkeywords
-1)) {
2153 dev
= keywords
[i
+1];
2154 memcpy(keywords
+i
,keywords
+(i
+2),(nrofkeywords
-i
-2)*sizeof(char *));
2158 if (!STRCMP(keywords
[i
],"wait")) {
2159 dwFlags
|= MCI_WAIT
;
2160 memcpy(keywords
+i
,keywords
+(i
+1),(nrofkeywords
-i
-1)*sizeof(char *));
2164 if (!STRCMP(keywords
[i
],"notify")) {
2165 dwFlags
|= MCI_NOTIFY
;
2166 memcpy(keywords
+i
,keywords
+(i
+1),(nrofkeywords
-i
-1)*sizeof(char *));
2173 /* determine wDevID and uDevTyp for all commands except "open" */
2174 if (STRCMP(cmd
,"open")!=0) {
2175 wDevID
= MMSYSTEM_FirstDevID();
2179 dname
=(SEGPTR
)GetOpenDrv(wDevID
)->lpstrAlias
;
2180 if (dname
==(SEGPTR
)NULL
)
2181 dname
=(SEGPTR
)GetOpenDrv(wDevID
)->lpstrDeviceType
;
2182 if ((dname
!=(SEGPTR
)NULL
)&&(!STRCMP(PTR_SEG_TO_LIN(dname
),dev
)))
2184 wDevID
= MMSYSTEM_NextDevID(wDevID
);
2185 if (!MMSYSTEM_DevIDValid(wDevID
)) {
2186 TRACE(mci
, "MAXMCIDRIVERS reached!\n");
2187 free(keywords
);free(cmd
);
2188 return MCIERR_INVALID_DEVICE_NAME
;
2191 uDevTyp
=GetDrv(wDevID
)->modp
.wType
;
2194 for (i
=0;MCISTR_cmdtable
[i
].cmd
!=NULL
;i
++) {
2195 if (!STRCMP(MCISTR_cmdtable
[i
].cmd
,cmd
)) {
2196 res
=MCISTR_cmdtable
[i
].fun(
2197 wDevID
,uDevTyp
,lpstrReturnString
,
2198 uReturnLength
,dev
,(LPSTR
*)keywords
,nrofkeywords
,
2199 dwFlags
,hwndCallback
2204 if (MCISTR_cmdtable
[i
].cmd
!=NULL
) {
2205 free(keywords
);free(cmd
);
2208 FIXME(mci
,"('%s', %p, %u, %X): unimplemented, please report.\n",
2209 lpstrCommand
, lpstrReturnString
, uReturnLength
, hwndCallback
);
2210 free(keywords
);free(cmd
);
2211 return MCIERR_MISSING_COMMAND_STRING
;