Release 960712
[wine/dcerpc.git] / multimedia / mcistring.c
blob5abd42adceca0ebedf6155b0bfbde3c75c19342b
1 /*
2 * MCI stringinterface
4 * Copyright 1995 Marcus Meissner
5 */
6 /* FIXME: special commands of device drivers should be handled by those drivers
7 */
9 #ifndef WINELIB
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <sys/ioctl.h>
17 #include "windows.h"
18 #include "ldt.h"
19 #include "callback.h"
20 #include "user.h"
21 #include "driver.h"
22 #include "mmsystem.h"
23 #include "stddebug.h"
24 #include "debug.h"
25 #include "xmalloc.h"
28 extern MCI_OPEN_DRIVER_PARMS mciDrv[MAXMCIDRIVERS];
30 /* FIXME: I need to remember the aliasname of a spec. driver.
31 * and this is the easiest way. *sigh*
33 extern MCI_OPEN_PARMS mciOpenDrv[MAXMCIDRIVERS];
35 LONG DrvDefDriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
36 DWORD dwParam1, DWORD dwParam2);
38 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
39 DWORD dwParam1, DWORD dwParam2);
40 LONG MIDI_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
41 DWORD dwParam1, DWORD dwParam2);
42 LONG CDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
43 DWORD dwParam1, DWORD dwParam2);
44 LONG ANIM_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
45 DWORD dwParam1, DWORD dwParam2);
47 /* The reason why I just don't lowercase the keywords array in
48 * mciSendString is left as an exercise to the reader.
50 #define STRCMP(x,y) lstrcmpi32A(x,y)
52 /* standard functionparameters for all functions */
53 #define _MCISTR_PROTO_ \
54 WORD wDevID,WORD uDevTyp,LPSTR lpstrReturnString,UINT uReturnLength,\
55 LPCSTR dev,LPSTR *keywords,UINT nrofkeywords,DWORD dwFlags
57 /* copy string to return pointer including necessary checks
58 * for use in mciSendString()
60 #define _MCI_STR(s) do {\
61 dprintf_mci(stddeb,"->returns \"%s\"",s);\
62 if (lpstrReturnString) {\
63 lstrcpyn32A(lpstrReturnString,s,uReturnLength);\
64 dprintf_mci(stddeb,"-->\"%s\"\n",lpstrReturnString);\
66 } while(0)
68 /* calling DriverProc. We need to pass the struct as SEGMENTED POINTER. */
69 #define _MCI_CALL_DRIVER(cmd,params) \
70 switch(uDevTyp) {\
71 case MCI_DEVTYPE_CD_AUDIO:\
72 res=CDAUDIO_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags, (DWORD)(params));\
73 break;\
74 case MCI_DEVTYPE_WAVEFORM_AUDIO:\
75 res=WAVE_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
76 break;\
77 case MCI_DEVTYPE_SEQUENCER:\
78 res=MIDI_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
79 break;\
80 case MCI_DEVTYPE_ANIMATION:\
81 res=ANIM_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,(DWORD)(params));\
82 break;\
83 case MCI_DEVTYPE_DIGITAL_VIDEO:\
84 dprintf_mci(stddeb,"_MCI_CALL_DRIVER //No DIGITAL_VIDEO yet !\n");\
85 res=MCIERR_DEVICE_NOT_INSTALLED;\
86 break;\
87 default:\
88 dprintf_mci(stddeb,"_MCI_CALL_DRIVER //Invalid Device Name '%s' !\n",dev);\
89 res=MCIERR_INVALID_DEVICE_NAME;\
90 break;\
92 /* we need to have strings in 16 bit space for some things
93 * FIXME: this is bad.
95 #define _MCI_STRDUP_TO_SEG(dest,source) {\
96 HANDLE x;\
97 x=USER_HEAP_ALLOC(strlen(source));\
98 dest=(LPSTR)MAKELONG(x,USER_HeapSel);\
99 strcpy(PTR_SEG_TO_LIN(dest),source);\
102 /* print a DWORD in the specified timeformat */
103 static void
104 _MCISTR_printtf(char *buf,UINT uDevType,DWORD timef,DWORD val) {
105 *buf='\0';
106 switch (timef) {
107 case MCI_FORMAT_MILLISECONDS:
108 case MCI_FORMAT_FRAMES:
109 case MCI_FORMAT_BYTES:
110 case MCI_FORMAT_SAMPLES:
111 case MCI_VD_FORMAT_TRACK:
112 /*case MCI_SEQ_FORMAT_SONGPTR: sameas MCI_VD_FORMAT_TRACK */
113 sprintf(buf,"%ld",val);
114 break;
115 case MCI_FORMAT_HMS:
116 /* well, the macros have the same content*/
117 /*FALLTRHOUGH*/
118 case MCI_FORMAT_MSF:
119 sprintf(buf,"%d:%d:%d",
120 MCI_HMS_HOUR(val),
121 MCI_HMS_MINUTE(val),
122 MCI_HMS_SECOND(val)
124 break;
125 case MCI_FORMAT_TMSF:
126 sprintf(buf,"%d:%d:%d:%d",
127 MCI_TMSF_TRACK(val),
128 MCI_TMSF_MINUTE(val),
129 MCI_TMSF_SECOND(val),
130 MCI_TMSF_FRAME(val)
132 break;
133 default:
134 fprintf(stdnimp,__FILE__":MCISTR_Status:missing timeformat for %ld, report.\n",timef);
135 strcpy(buf,"0"); /* hmm */
136 break;
138 return;
140 /* possible different return types */
141 #define _MCISTR_int 1
142 #define _MCISTR_time 2
143 #define _MCISTR_bool 3
144 #define _MCISTR_tfname 4
145 #define _MCISTR_mode 5
146 #define _MCISTR_divtype 6
147 #define _MCISTR_seqtype 7
148 #define _MCISTR_vdmtype 8
149 #define _MCISTR_devtype 9
151 static void
152 _MCISTR_convreturn(int type,DWORD dwReturn,LPSTR lpstrReturnString,
153 WORD uReturnLength,WORD uDevTyp,int timef
155 switch (type) {
156 case _MCISTR_vdmtype:
157 switch (dwReturn) {
158 case MCI_VD_MEDIA_CLV:_MCI_STR("CLV");break;
159 case MCI_VD_MEDIA_CAV:_MCI_STR("CAV");break;
160 default:
161 case MCI_VD_MEDIA_OTHER:_MCI_STR("other");break;
163 break;
164 case _MCISTR_seqtype:
165 switch (dwReturn) {
166 case MCI_SEQ_NONE:_MCI_STR("none");break;
167 case MCI_SEQ_SMPTE:_MCI_STR("smpte");break;
168 case MCI_SEQ_FILE:_MCI_STR("file");break;
169 case MCI_SEQ_MIDI:_MCI_STR("midi");break;
170 default:fprintf(stdnimp,__FILE__":MCISTR_Status:missing sequencer mode %ld\n",dwReturn);
172 break;
173 case _MCISTR_mode:
174 switch (dwReturn) {
175 case MCI_MODE_NOT_READY:_MCI_STR("not ready");break;
176 case MCI_MODE_STOP:_MCI_STR("stopped");break;
177 case MCI_MODE_PLAY:_MCI_STR("playing");break;
178 case MCI_MODE_RECORD:_MCI_STR("recording");break;
179 case MCI_MODE_SEEK:_MCI_STR("seeking");break;
180 case MCI_MODE_PAUSE:_MCI_STR("paused");break;
181 case MCI_MODE_OPEN:_MCI_STR("open");break;
182 default:break;
184 break;
185 case _MCISTR_bool:
186 if (dwReturn)
187 _MCI_STR("true");
188 else
189 _MCI_STR("false");
190 break;
191 case _MCISTR_int:{
192 char buf[16];
193 sprintf(buf,"%ld",dwReturn);
194 _MCI_STR(buf);
195 break;
197 case _MCISTR_time: {
198 char buf[100];
199 _MCISTR_printtf(buf,uDevTyp,timef,dwReturn);
200 _MCI_STR(buf);
201 break;
203 case _MCISTR_tfname:
204 switch (timef) {
205 case MCI_FORMAT_MILLISECONDS:_MCI_STR("milliseconds");break;
206 case MCI_FORMAT_FRAMES:_MCI_STR("frames");break;
207 case MCI_FORMAT_BYTES:_MCI_STR("bytes");break;
208 case MCI_FORMAT_SAMPLES:_MCI_STR("samples");break;
209 case MCI_FORMAT_HMS:_MCI_STR("hms");break;
210 case MCI_FORMAT_MSF:_MCI_STR("msf");break;
211 case MCI_FORMAT_TMSF:_MCI_STR("tmsf");break;
212 default:
213 fprintf(stdnimp,__FILE__":MCISTR_Status:missing timeformat for %d, report.\n",timef);
214 break;
216 break;
217 case _MCISTR_divtype:
218 switch (dwReturn) {
219 case MCI_SEQ_DIV_PPQN:_MCI_STR("PPQN");break;
220 case MCI_SEQ_DIV_SMPTE_24:_MCI_STR("SMPTE 24 frame");break;
221 case MCI_SEQ_DIV_SMPTE_25:_MCI_STR("SMPTE 25 frame");break;
222 case MCI_SEQ_DIV_SMPTE_30:_MCI_STR("SMPTE 30 frame");break;
223 case MCI_SEQ_DIV_SMPTE_30DROP:_MCI_STR("SMPTE 30 frame drop");break;
225 case _MCISTR_devtype:
226 switch (dwReturn) {
227 case MCI_DEVTYPE_VCR:_MCI_STR("vcr");break;
228 case MCI_DEVTYPE_VIDEODISC:_MCI_STR("videodisc");break;
229 case MCI_DEVTYPE_CD_AUDIO:_MCI_STR("cd audio");break;
230 case MCI_DEVTYPE_OVERLAY:_MCI_STR("overlay");break;
231 case MCI_DEVTYPE_DAT:_MCI_STR("dat");break;
232 case MCI_DEVTYPE_SCANNER:_MCI_STR("scanner");break;
233 case MCI_DEVTYPE_ANIMATION:_MCI_STR("animation");break;
234 case MCI_DEVTYPE_DIGITAL_VIDEO:_MCI_STR("digital video");break;
235 case MCI_DEVTYPE_OTHER:_MCI_STR("other");break;
236 case MCI_DEVTYPE_WAVEFORM_AUDIO:_MCI_STR("waveform audio");break;
237 case MCI_DEVTYPE_SEQUENCER:_MCI_STR("sequencer");break;
238 default:fprintf(stdnimp,__FILE__":_MCISTR_convreturn:unknown device type %ld, report.\n",dwReturn);break;
240 break;
241 default:
242 fprintf(stdnimp,__FILE__":_MCISTR_convreturn:unknown resulttype %d, report.\n",type);
243 break;
247 #define FLAG1(str,flag) \
248 if (!STRCMP(keywords[i],str)) {\
249 dwFlags |= flag;\
250 i++;\
251 continue;\
253 #define FLAG2(str1,str2,flag) \
254 if (!STRCMP(keywords[i],str1) && (i+1<nrofkeywords) && !STRCMP(keywords[i+1],str2)) {\
255 dwFlags |= flag;\
256 i+=2;\
257 continue;\
260 /* All known subcommands are implemented in single functions to avoid
261 * bloat and a xxxx lines long mciSendString(). All commands are of the
262 * format MCISTR_Cmd(_MCISTR_PROTO_) where _MCISTR_PROTO_ is the above
263 * defined line of arguments. (This is just for easy enhanceability.)
264 * All functions return the MCIERR_ errorvalue as DWORD. Returnvalues
265 * for the calls are in lpstrReturnString (If I mention return values
266 * in function headers, I mean returnvalues in lpstrReturnString.)
267 * Integers are sprintf("%d")ed integers. Boolean values are
268 * "true" and "false".
269 * timeformat depending values are "%d" "%d:%d" "%d:%d:%d" "%d:%d:%d:%d"
270 * FIXME: is above line correct?
272 * Preceding every function is a list of implemented/known arguments.
273 * Feel free to add missing arguments.
278 * Opens the specified MCI driver.
279 * Arguments: <name>
280 * Optional:
281 * "shareable"
282 * "alias <aliasname>"
283 * "element <elementname>"
284 * Additional:
285 * waveform audio:
286 * "buffer <nrBytesPerSec>"
287 * Animation:
288 * "nostatic" increaste nr of nonstatic colours
289 * "parent <windowhandle>"
290 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
291 * "style child" WS_CHILD
292 * "style overlap" WS_OVERLAPPED
293 * "style popup" WS_POPUP
294 * Overlay:
295 * "parent <windowhandle>"
296 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
297 * "style child" WS_CHILD
298 * "style overlap" WS_OVERLAPPED
299 * "style popup" WS_POPUP
300 * Returns nothing.
302 static DWORD
303 MCISTR_Open(_MCISTR_PROTO_) {
304 int res,i;
305 char *s;
306 union {
307 MCI_OPEN_PARMS openParams;
308 MCI_WAVE_OPEN_PARMS waveopenParams;
309 MCI_ANIM_OPEN_PARMS animopenParams;
310 MCI_OVLY_OPEN_PARMS ovlyopenParams;
311 } U;
313 U.openParams.lpstrElementName = NULL;
314 s=strchr(dev,'!');
315 if (s!=NULL) {
316 *s++='\0';
317 _MCI_STRDUP_TO_SEG(U.openParams.lpstrElementName,s);
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;
329 } else {
330 return MCIERR_INVALID_DEVICE_NAME;
332 wDevID=0;
333 while(mciDrv[wDevID].wType) {
334 if (++wDevID>=MAXMCIDRIVERS) {
335 dprintf_mci(stddeb, __FILE__":MCISTR_Open:MAXMCIDRIVERS reached!\n");
336 return MCIERR_INTERNAL;
339 mciDrv[wDevID].wType = uDevTyp;
340 mciDrv[wDevID].wDeviceID = wDevID;
341 U.openParams.dwCallback = 0;
342 U.openParams.wDeviceID = wDevID;
343 U.ovlyopenParams.dwStyle = 0;
344 U.animopenParams.dwStyle = 0;
346 _MCI_STRDUP_TO_SEG(U.openParams.lpstrDeviceType,dev);
347 U.openParams.lpstrAlias = NULL;
348 dwFlags |= MCI_OPEN_TYPE;
349 i=0;
350 while (i<nrofkeywords) {
351 FLAG1("shareable",MCI_OPEN_SHAREABLE);
352 if (!strcmp(keywords[i],"alias") && (i+1<nrofkeywords)) {
353 dwFlags |= MCI_OPEN_ALIAS;
354 _MCI_STRDUP_TO_SEG(U.openParams.lpstrAlias,keywords[i]);
355 i+=2;
356 continue;
358 if (!strcmp(keywords[i],"element") && (i+1<nrofkeywords)) {
359 dwFlags |= MCI_OPEN_ELEMENT;
360 _MCI_STRDUP_TO_SEG(U.openParams.lpstrElementName,keywords[i]);
361 i+=2;
362 continue;
364 switch (uDevTyp) {
365 case MCI_DEVTYPE_ANIMATION:
366 case MCI_DEVTYPE_DIGITAL_VIDEO:
367 FLAG1("nostatic",MCI_ANIM_OPEN_NOSTATIC);
368 if (!STRCMP(keywords[i],"parent") && (i+1<nrofkeywords)) {
369 dwFlags |= MCI_ANIM_OPEN_PARENT;
370 sscanf(keywords[i+1],"%hu",&(U.animopenParams.hWndParent));
371 i+=2;
372 continue;
374 if (!STRCMP(keywords[i],"style") && (i+1<nrofkeywords)) {
375 DWORD st;
377 dwFlags |= MCI_ANIM_OPEN_WS;
378 if (!STRCMP(keywords[i+1],"popup")) {
379 U.animopenParams.dwStyle |= WS_POPUP;
380 } else if (!STRCMP(keywords[i+1],"overlap")) {
381 U.animopenParams.dwStyle |= WS_OVERLAPPED;
382 } else if (!STRCMP(keywords[i+1],"child")) {
383 U.animopenParams.dwStyle |= WS_CHILD;
384 } else if (sscanf(keywords[i+1],"%ld",&st)) {
385 U.animopenParams.dwStyle |= st;
386 } else
387 fprintf(stdnimp,__FILE__":MCISTR_Open:unknown 'style' keyword %s, please report.\n",keywords[i+1]);
388 i+=2;
389 continue;
391 break;
392 case MCI_DEVTYPE_WAVEFORM_AUDIO:
393 if (!STRCMP(keywords[i],"buffer") && (i+1<nrofkeywords)) {
394 dwFlags |= MCI_WAVE_OPEN_BUFFER;
395 sscanf(keywords[i+1],"%ld",&(U.waveopenParams.dwBufferSeconds));
397 break;
398 case MCI_DEVTYPE_OVERLAY:
399 /* looks just like anim, but without NOSTATIC */
400 if (!STRCMP(keywords[i],"parent") && (i+1<nrofkeywords)) {
401 dwFlags |= MCI_OVLY_OPEN_PARENT;
402 sscanf(keywords[i+1],"%hd",&(U.ovlyopenParams.hWndParent));
403 i+=2;
404 continue;
406 if (!STRCMP(keywords[i],"style") && (i+1<nrofkeywords)) {
407 DWORD st;
409 dwFlags |= MCI_OVLY_OPEN_WS;
410 if (!STRCMP(keywords[i+1],"popup")) {
411 U.ovlyopenParams.dwStyle |= WS_POPUP;
412 } else if (!STRCMP(keywords[i+1],"overlap")) {
413 U.ovlyopenParams.dwStyle |= WS_OVERLAPPED;
414 } else if (!STRCMP(keywords[i+1],"child")) {
415 U.ovlyopenParams.dwStyle |= WS_CHILD;
416 } else if (sscanf(keywords[i+1],"%ld",&st)) {
417 U.ovlyopenParams.dwStyle |= st;
418 } else
419 fprintf(stdnimp,__FILE__":MCISTR_Open:unknown 'style' keyword %s, please report.\n",keywords[i+1]);
420 i+=2;
421 continue;
423 break;
425 fprintf(stdnimp,__FILE__":MCISTR_Open:unknown parameter passed %s, please report.\n",keywords[i]);
426 i++;
428 _MCI_CALL_DRIVER( MCI_OPEN, MAKE_SEGPTR(&U) );
429 if (res==0)
430 memcpy(&mciOpenDrv[wDevID],&U.openParams,sizeof(MCI_OPEN_PARMS));
431 return res;
434 /* A help function for a lot of others ...
435 * for instance status/play/record/seek etc.
437 DWORD
438 _MCISTR_determine_timeformat(LPCSTR dev,WORD wDevID,WORD uDevTyp,int *timef) {
439 MCI_STATUS_PARMS statusParams;
440 DWORD dwFlags;
441 int res;
443 dwFlags = MCI_STATUS_ITEM;
444 statusParams.dwItem = MCI_STATUS_TIME_FORMAT;
445 statusParams.dwReturn = 0;
446 _MCI_CALL_DRIVER( MCI_STATUS, MAKE_SEGPTR(&statusParams) );
447 if (res==0) *timef=statusParams.dwReturn;
448 return res;
451 /* query status of MCI drivers
452 * Arguments:
453 * Required:
454 * "mode" - returns "not ready" "paused" "playing" "stopped" "open"
455 * "parked" "recording" "seeking" ....
456 * Basics:
457 * "current track" - returns current track as integer
458 * "length [track <nr>]" - returns length [of track <nr>] in current
459 * timeformat
460 * "number of tracks" - returns number of tracks as integer
461 * "position [track <nr>]" - returns position [in track <nr>] in current
462 * timeformat
463 * "ready" - checks if device is ready to play, -> bool
464 * "start position" - returns start position in timeformat
465 * "time format" - returns timeformat (list of possible values:
466 * "ms" "msf" "milliseconds" "hmsf" "tmsf" "frames"
467 * "bytes" "samples" "hms")
468 * "media present" - returns if media is present as bool
469 * Animation:
470 * "forward" - returns "true" if device is playing forwards
471 * "speed" - returns speed for device
472 * "palette handle" - returns palette handle
473 * "window handle" - returns window handle
474 * "stretch" - returns stretch bool
475 * MIDI sequencer:
476 * "division type" - ? returns "PPQN" "SMPTE 24 frame"
477 * "SMPTE 25 frame" "SMPTE 30 frame" "SMPTE 30 drop frame"
478 * "tempo" - current tempo in (PPQN? speed in frames, SMPTE*? speed in hsmf)
479 * "offset" - offset in dito.
480 * "port" - midi port as integer
481 * "slave" - slave device ("midi","file","none","smpte")
482 * "master" - masterdevice (dito.)
483 * Overlay:
484 * "window handle" - see animation
485 * "stretch" - dito
486 * Video Disc:
487 * "speed" - speed as integer
488 * "forward" - returns bool (when playing forward)
489 * "side" - returns 1 or 2
490 * "media type" - returns "CAV" "CLV" "other"
491 * "disc size" - returns "8" or "12"
492 * WAVEFORM audio:
493 * "input" - base queries on input set
494 * "output" - base queries on output set
495 * "format tag" - return integer format tag
496 * "channels" - return integer nr of channels
497 * "bytespersec" - return average nr of bytes/sec
498 * "samplespersec" - return nr of samples per sec
499 * "bitspersample" - return bitspersample
500 * "alignment" - return block alignment
501 * "level" - return level?
504 #define ITEM1(str,item,xtype) \
505 if (!STRCMP(keywords[i],str)) {\
506 statusParams.dwItem = item;\
507 type = xtype;\
508 i++;\
509 continue;\
511 #define ITEM2(str1,str2,item,xtype) \
512 if ( !STRCMP(keywords[i],str1) &&\
513 (i+1<nrofkeywords) &&\
514 !STRCMP(keywords[i+1],str2)\
515 ) {\
516 statusParams.dwItem = item;\
517 type = xtype;\
518 i+=2;\
519 continue;\
521 #define ITEM3(str1,str2,str3,item,xtype) \
522 if ( !STRCMP(keywords[i],str1) &&\
523 (i+2<nrofkeywords) &&\
524 !STRCMP(keywords[i+1],str2) &&\
525 !STRCMP(keywords[i+2],str3)\
526 ) {\
527 statusParams.dwItem = item;\
528 type = xtype;\
529 i+=3;\
530 continue;\
532 static DWORD
533 MCISTR_Status(_MCISTR_PROTO_) {
534 MCI_STATUS_PARMS statusParams;
535 int type = 0,i,res,timef;
537 statusParams.dwCallback = 0;
538 dwFlags |= MCI_STATUS_ITEM;
539 res = _MCISTR_determine_timeformat(dev,wDevID,uDevTyp,&timef);
540 if (res) return res;
542 statusParams.dwReturn = 0;
543 statusParams.dwItem = 0;
544 i = 0;
546 while (i<nrofkeywords) {
547 if (!STRCMP(keywords[i],"track") && (i+1<nrofkeywords)) {
548 sscanf(keywords[i+1],"%ld",&(statusParams.dwTrack));
549 dwFlags |= MCI_TRACK;
550 i+=2;
551 continue;
553 FLAG1("start",MCI_STATUS_START);
554 /* generic things */
555 ITEM2("current","track",MCI_STATUS_CURRENT_TRACK,_MCISTR_time);
556 ITEM2("time","format",MCI_STATUS_TIME_FORMAT,_MCISTR_tfname);
557 ITEM1("ready",MCI_STATUS_READY,_MCISTR_bool);
558 ITEM1("mode",MCI_STATUS_MODE,_MCISTR_mode);
559 ITEM3("number","of","tracks",MCI_STATUS_NUMBER_OF_TRACKS,_MCISTR_int);
560 ITEM1("length",MCI_STATUS_LENGTH,_MCISTR_time);
561 ITEM1("position",MCI_STATUS_POSITION,_MCISTR_time);
562 ITEM2("media","present",MCI_STATUS_MEDIA_PRESENT,_MCISTR_bool);
564 switch (uDevTyp) {
565 case MCI_DEVTYPE_ANIMATION:
566 case MCI_DEVTYPE_DIGITAL_VIDEO:
567 ITEM2("palette","handle",MCI_ANIM_STATUS_HPAL,_MCISTR_int);
568 ITEM2("window","handle",MCI_ANIM_STATUS_HWND,_MCISTR_int);
569 ITEM1("stretch",MCI_ANIM_STATUS_STRETCH,_MCISTR_bool);
570 ITEM1("speed",MCI_ANIM_STATUS_SPEED,_MCISTR_int);
571 ITEM1("forward",MCI_ANIM_STATUS_FORWARD,_MCISTR_bool);
572 break;
573 case MCI_DEVTYPE_SEQUENCER:
574 /* just completing the list, not working correctly */
575 ITEM2("division","type",MCI_SEQ_STATUS_DIVTYPE,_MCISTR_divtype);
576 /* tempo ... PPQN in frames/second, SMPTE in hmsf */
577 ITEM1("tempo",MCI_SEQ_STATUS_TEMPO,_MCISTR_int);
578 ITEM1("port",MCI_SEQ_STATUS_PORT,_MCISTR_int);
579 ITEM1("slave",MCI_SEQ_STATUS_SLAVE,_MCISTR_seqtype);
580 ITEM1("master",MCI_SEQ_STATUS_SLAVE,_MCISTR_seqtype);
581 /* offset ... PPQN in frames/second, SMPTE in hmsf */
582 ITEM1("offset",MCI_SEQ_STATUS_SLAVE,_MCISTR_time);
583 break;
584 case MCI_DEVTYPE_OVERLAY:
585 ITEM2("window","handle",MCI_OVLY_STATUS_HWND,_MCISTR_int);
586 ITEM1("stretch",MCI_OVLY_STATUS_STRETCH,_MCISTR_bool);
587 break;
588 case MCI_DEVTYPE_VIDEODISC:
589 ITEM1("speed",MCI_VD_STATUS_SPEED,_MCISTR_int);
590 ITEM1("forward",MCI_VD_STATUS_FORWARD,_MCISTR_bool);
591 ITEM1("side",MCI_VD_STATUS_SIDE,_MCISTR_int);
592 ITEM2("media","type",MCI_VD_STATUS_SIDE,_MCISTR_vdmtype);
593 /* returns 8 or 12 */
594 ITEM2("disc","size",MCI_VD_STATUS_DISC_SIZE,_MCISTR_int);
595 break;
596 case MCI_DEVTYPE_WAVEFORM_AUDIO:
597 /* I am not quite sure if foll. 2 lines are right. */
598 FLAG1("input",MCI_WAVE_INPUT);
599 FLAG1("output",MCI_WAVE_OUTPUT);
601 ITEM2("format","tag",MCI_WAVE_STATUS_FORMATTAG,_MCISTR_int);
602 ITEM1("channels",MCI_WAVE_STATUS_CHANNELS,_MCISTR_int);
603 ITEM1("bytespersec",MCI_WAVE_STATUS_AVGBYTESPERSEC,_MCISTR_int);
604 ITEM1("samplespersec",MCI_WAVE_STATUS_SAMPLESPERSEC,_MCISTR_int);
605 ITEM1("bitspersample",MCI_WAVE_STATUS_BITSPERSAMPLE,_MCISTR_int);
606 ITEM1("alignment",MCI_WAVE_STATUS_BLOCKALIGN,_MCISTR_int);
607 ITEM1("level",MCI_WAVE_STATUS_LEVEL,_MCISTR_int);
608 break;
610 fprintf(stdnimp,__FILE__":MCISTR_Status:unknown keyword '%s'\n",keywords[i]);
611 i++;
613 if (!statusParams.dwItem)
614 return MCIERR_MISSING_STRING_ARGUMENT;
616 _MCI_CALL_DRIVER( MCI_STATUS, MAKE_SEGPTR(&statusParams) );
617 if (res==0)
618 _MCISTR_convreturn(type,statusParams.dwReturn,lpstrReturnString,uReturnLength,uDevTyp,timef);
619 return res;
621 #undef ITEM1
622 #undef ITEM2
623 #undef ITEM3
625 /* set specified parameters in respective MCI drivers
626 * Arguments:
627 * "door open" eject media or somesuch
628 * "door close" load media
629 * "time format <timeformatname>" "ms" "milliseconds" "msf" "hmsf"
630 * "tmsf" "SMPTE 24" "SMPTE 25" "SMPTE 30"
631 * "SMPTE drop 30"
632 * "audio [all|left|right] [on|off]" sets specified audiochannel on or off
633 * "video [on|off]" sets video on/off
634 * Waveform audio:
635 * "formattag pcm" sets format to pcm
636 * "formattag <nr>" sets integer formattag value
637 * "any input" accept input from any known source
638 * "any output" output to any known destination
639 * "input <nr>" input from source <nr>
640 * "output <nr>" output to destination <nr>
641 * "channels <nr>" sets nr of channels
642 * "bytespersec <nr>" sets average bytes per second
643 * "samplespersec <nr>" sets average samples per second (1 sample can
644 * be 2 bytes!)
645 * "alignment <nr>" sets the blockalignment to <nr>
646 * "bitspersample <nr>" sets the nr of bits per sample
647 * Sequencer:
648 * "master [midi|file|smpte|none]" sets the midi master device
649 * "slave [midi|file|smpte|none]" sets the midi master device
650 * "port mapper" midioutput to portmapper
651 * "port <nr>" midioutput to specified port
652 * "tempo <nr>" tempo of track (depends on timeformat/divtype)
653 * "offset <nr>" start offset?
655 static DWORD
656 MCISTR_Set(_MCISTR_PROTO_) {
657 union {
658 MCI_SET_PARMS setParams;
659 MCI_WAVE_SET_PARMS wavesetParams;
660 MCI_SEQ_SET_PARMS seqsetParams;
661 } U;
662 int i,res;
664 U.setParams.dwCallback = 0;
665 i = 0;
666 while (i<nrofkeywords) {
667 FLAG2("door","open",MCI_SET_DOOR_OPEN);
668 FLAG2("door","closed",MCI_SET_DOOR_CLOSED);
670 if ( !STRCMP(keywords[i],"time") &&
671 (i+2<nrofkeywords) &&
672 !STRCMP(keywords[i+1],"format")
674 dwFlags |= MCI_SET_TIME_FORMAT;
676 /* FIXME:is this a shortcut for milliseconds or
677 * minutes:seconds? */
678 if (!STRCMP(keywords[i+2],"ms"))
679 U.setParams.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
681 if (!STRCMP(keywords[i+2],"milliseconds"))
682 U.setParams.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
683 if (!STRCMP(keywords[i+2],"msf"))
684 U.setParams.dwTimeFormat = MCI_FORMAT_MSF;
685 if (!STRCMP(keywords[i+2],"hms"))
686 U.setParams.dwTimeFormat = MCI_FORMAT_HMS;
687 if (!STRCMP(keywords[i+2],"frames"))
688 U.setParams.dwTimeFormat = MCI_FORMAT_FRAMES;
689 if (!STRCMP(keywords[i+2],"track"))
690 U.setParams.dwTimeFormat = MCI_VD_FORMAT_TRACK;
691 if (!STRCMP(keywords[i+2],"bytes"))
692 U.setParams.dwTimeFormat = MCI_FORMAT_BYTES;
693 if (!STRCMP(keywords[i+2],"samples"))
694 U.setParams.dwTimeFormat = MCI_FORMAT_SAMPLES;
695 if (!STRCMP(keywords[i+2],"tmsf"))
696 U.setParams.dwTimeFormat = MCI_FORMAT_TMSF;
697 if ( !STRCMP(keywords[i+2],"song") &&
698 (i+3<nrofkeywords) &&
699 !STRCMP(keywords[i+3],"pointer")
701 U.setParams.dwTimeFormat = MCI_SEQ_FORMAT_SONGPTR;
702 if (!STRCMP(keywords[i+2],"smpte") && (i+3<nrofkeywords)) {
703 if (!STRCMP(keywords[i+3],"24"))
704 U.setParams.dwTimeFormat = MCI_FORMAT_SMPTE_24;
705 if (!STRCMP(keywords[i+3],"25"))
706 U.setParams.dwTimeFormat = MCI_FORMAT_SMPTE_25;
707 if (!STRCMP(keywords[i+3],"30"))
708 U.setParams.dwTimeFormat = MCI_FORMAT_SMPTE_30;
709 if (!STRCMP(keywords[i+3],"drop") && (i+4<nrofkeywords) && !STRCMP(keywords[i+4],"30")) {
710 U.setParams.dwTimeFormat = MCI_FORMAT_SMPTE_30DROP;
711 i++;
713 i++;
714 /*FALLTHROUGH*/
716 i+=3;
717 continue;
719 if (!STRCMP(keywords[i],"audio") && (i+1<nrofkeywords)) {
720 dwFlags |= MCI_SET_AUDIO;
721 if (!STRCMP(keywords[i+1],"all"))
722 U.setParams.dwAudio = MCI_SET_AUDIO_ALL;
723 if (!STRCMP(keywords[i+1],"left"))
724 U.setParams.dwAudio = MCI_SET_AUDIO_LEFT;
725 if (!STRCMP(keywords[i+1],"right"))
726 U.setParams.dwAudio = MCI_SET_AUDIO_RIGHT;
727 i+=2;
728 continue;
730 FLAG1("video",MCI_SET_VIDEO);
731 FLAG1("on",MCI_SET_ON);
732 FLAG1("off",MCI_SET_OFF);
733 switch (uDevTyp) {
734 case MCI_DEVTYPE_WAVEFORM_AUDIO:
735 FLAG2("any","input",MCI_WAVE_SET_ANYINPUT);
736 FLAG2("any","output",MCI_WAVE_SET_ANYOUTPUT);
738 if ( !STRCMP(keywords[i],"formattag") &&
739 (i+1<nrofkeywords) &&
740 !STRCMP(keywords[i+1],"pcm")
742 dwFlags |= MCI_WAVE_SET_FORMATTAG;
743 U.wavesetParams.wFormatTag = WAVE_FORMAT_PCM;
744 i+=2;
745 continue;
748 /* <keyword> <integer> */
749 #define WII(str,flag,fmt,element) \
750 if (!STRCMP(keywords[i],str) && (i+1<nrofkeywords)) {\
751 sscanf(keywords[i+1],fmt,&(U.wavesetParams. element ));\
752 dwFlags |= flag;\
753 i+=2;\
754 continue;\
756 WII("formattag",MCI_WAVE_SET_FORMATTAG,"%hu",wFormatTag);
757 WII("channels",MCI_WAVE_SET_CHANNELS,"%hu",nChannels);
758 WII("bytespersec",MCI_WAVE_SET_AVGBYTESPERSEC,"%lu",nAvgBytesPerSec);
759 WII("samplespersec",MCI_WAVE_SET_SAMPLESPERSEC,"%lu",nSamplesPerSec);
760 WII("alignment",MCI_WAVE_SET_BLOCKALIGN,"%hu",nBlockAlign);
761 WII("bitspersample",MCI_WAVE_SET_BITSPERSAMPLE,"%hu",wBitsPerSample);
762 WII("input",MCI_WAVE_INPUT,"%hu",wInput);
763 WII("output",MCI_WAVE_OUTPUT,"%hu",wOutput);
764 #undef WII
765 break;
766 case MCI_DEVTYPE_SEQUENCER:
767 if (!STRCMP(keywords[i],"master") && (i+1<nrofkeywords)) {
768 dwFlags |= MCI_SEQ_SET_MASTER;
769 if (!STRCMP(keywords[i+1],"midi"))
770 U.seqsetParams.dwMaster = MCI_SEQ_MIDI;
771 if (!STRCMP(keywords[i+1],"file"))
772 U.seqsetParams.dwMaster = MCI_SEQ_FILE;
773 if (!STRCMP(keywords[i+1],"smpte"))
774 U.seqsetParams.dwMaster = MCI_SEQ_SMPTE;
775 if (!STRCMP(keywords[i+1],"none"))
776 U.seqsetParams.dwMaster = MCI_SEQ_NONE;
777 i+=2;
778 continue;
780 if (!STRCMP(keywords[i],"slave") && (i+1<nrofkeywords)) {
781 dwFlags |= MCI_SEQ_SET_SLAVE;
782 if (!STRCMP(keywords[i+1],"midi"))
783 U.seqsetParams.dwMaster = MCI_SEQ_MIDI;
784 if (!STRCMP(keywords[i+1],"file"))
785 U.seqsetParams.dwMaster = MCI_SEQ_FILE;
786 if (!STRCMP(keywords[i+1],"smpte"))
787 U.seqsetParams.dwMaster = MCI_SEQ_SMPTE;
788 if (!STRCMP(keywords[i+1],"none"))
789 U.seqsetParams.dwMaster = MCI_SEQ_NONE;
790 i+=2;
791 continue;
793 if ( !STRCMP(keywords[i],"port") &&
794 (i+1<nrofkeywords) &&
795 !STRCMP(keywords[i+1],"mapper")
797 U.seqsetParams.dwPort=-1;/* FIXME:not sure*/
798 dwFlags |= MCI_SEQ_SET_PORT;
799 i+=2;
800 continue;
802 #define SII(str,flag,element) \
803 if (!STRCMP(keywords[i],str) && (i+1<nrofkeywords)) {\
804 sscanf(keywords[i+1],"%ld",&(U.seqsetParams. element ));\
805 dwFlags |= flag;\
806 i+=2;\
807 continue;\
809 SII("tempo",MCI_SEQ_SET_TEMPO,dwTempo);
810 SII("port",MCI_SEQ_SET_PORT,dwPort);
811 SII("offset",MCI_SEQ_SET_PORT,dwOffset);
813 i++;
815 if (!dwFlags)
816 return MCIERR_MISSING_STRING_ARGUMENT;
817 _MCI_CALL_DRIVER( MCI_SET, MAKE_SEGPTR(&U) );
818 return res;
821 /* specify break key
822 * Arguments:
823 * "off" disable break
824 * "on <keyid>" enable break on key with keyid
825 * (I strongly suspect, that there is another parameter:
826 * "window <handle>"
827 * but I don't see it mentioned in my documentation.
828 * Returns nothing.
830 static DWORD
831 MCISTR_Break(_MCISTR_PROTO_) {
832 MCI_BREAK_PARMS breakParams;
833 int res,i;
835 /*breakParams.hwndBreak ? */
836 i=0;while (i<nrofkeywords) {
837 FLAG1("off",MCI_BREAK_OFF);
838 if (!strcmp(keywords[i],"on") && (nrofkeywords>i+1)) {
839 dwFlags&=~MCI_BREAK_OFF;
840 dwFlags|=MCI_BREAK_KEY;
841 sscanf(keywords[i+1],"%d",&(breakParams.nVirtKey));
842 i+=2;
843 continue;
845 i++;
847 _MCI_CALL_DRIVER( MCI_BREAK, MAKE_SEGPTR(&breakParams) );
848 return res;
851 #define ITEM1(str,item,xtype) \
852 if (!STRCMP(keywords[i],str)) {\
853 gdcParams.dwItem = item;\
854 type = xtype;\
855 i++;\
856 continue;\
858 #define ITEM2(str1,str2,item,xtype) \
859 if ( !STRCMP(keywords[i],str1) &&\
860 (i+1<nrofkeywords) &&\
861 !STRCMP(keywords[i+1],str2)\
862 ) {\
863 gdcParams.dwItem = item;\
864 type = xtype;\
865 i+=2;\
866 continue;\
868 #define ITEM3(str1,str2,str3,item,xtype) \
869 if ( !STRCMP(keywords[i],str1) &&\
870 (i+2<nrofkeywords) &&\
871 !STRCMP(keywords[i+1],str2) &&\
872 !STRCMP(keywords[i+2],str3)\
873 ) {\
874 gdcParams.dwItem = item;\
875 type = xtype;\
876 i+=3;\
877 continue;\
879 /* get device capabilities of MCI drivers
880 * Arguments:
881 * Generic:
882 * "device type" returns device name as string
883 * "has audio" returns bool
884 * "has video" returns bool
885 * "uses files" returns bool
886 * "compound device" returns bool
887 * "can record" returns bool
888 * "can play" returns bool
889 * "can eject" returns bool
890 * "can save" returns bool
891 * Animation:
892 * "palettes" returns nr of available palette entries
893 * "windows" returns nr of available windows
894 * "can reverse" returns bool
895 * "can stretch" returns bool
896 * "slow play rate" returns the slow playrate
897 * "fast play rate" returns the fast playrate
898 * "normal play rate" returns the normal playrate
899 * Overlay:
900 * "windows" returns nr of available windows
901 * "can stretch" returns bool
902 * "can freeze" returns bool
903 * Videodisc:
904 * "cav" assume CAV discs (default if no disk inserted)
905 * "clv" assume CLV discs
906 * "can reverse" returns bool
907 * "slow play rate" returns the slow playrate
908 * "fast play rate" returns the fast playrate
909 * "normal play rate" returns the normal playrate
910 * Waveform audio:
911 * "inputs" returns nr of inputdevices
912 * "outputs" returns nr of outputdevices
914 static DWORD
915 MCISTR_Capability(_MCISTR_PROTO_) {
916 MCI_GETDEVCAPS_PARMS gdcParams;
917 int type=0,i,res;
919 gdcParams.dwCallback = 0;
920 if (!nrofkeywords)
921 return MCIERR_MISSING_STRING_ARGUMENT;
922 /* well , thats default */
923 dwFlags |= MCI_GETDEVCAPS_ITEM;
924 gdcParams.dwItem = 0;
925 i=0;
926 while (i<nrofkeywords) {
927 ITEM2("device","type",MCI_GETDEVCAPS_DEVICE_TYPE,_MCISTR_devtype);
928 ITEM2("has","audio",MCI_GETDEVCAPS_HAS_AUDIO,_MCISTR_bool);
929 ITEM2("has","video",MCI_GETDEVCAPS_HAS_VIDEO,_MCISTR_bool);
930 ITEM2("uses","files",MCI_GETDEVCAPS_USES_FILES,_MCISTR_bool);
931 ITEM2("compound","device",MCI_GETDEVCAPS_COMPOUND_DEVICE,_MCISTR_bool);
932 ITEM2("can","record",MCI_GETDEVCAPS_CAN_RECORD,_MCISTR_bool);
933 ITEM2("can","play",MCI_GETDEVCAPS_CAN_PLAY,_MCISTR_bool);
934 ITEM2("can","eject",MCI_GETDEVCAPS_CAN_EJECT,_MCISTR_bool);
935 ITEM2("can","save",MCI_GETDEVCAPS_CAN_SAVE,_MCISTR_bool);
936 switch (uDevTyp) {
937 case MCI_DEVTYPE_ANIMATION:
938 ITEM1("palettes",MCI_ANIM_GETDEVCAPS_PALETTES,_MCISTR_int);
939 ITEM1("windows",MCI_ANIM_GETDEVCAPS_MAX_WINDOWS,_MCISTR_int);
940 ITEM2("can","reverse",MCI_ANIM_GETDEVCAPS_CAN_REVERSE,_MCISTR_bool);
941 ITEM2("can","stretch",MCI_ANIM_GETDEVCAPS_CAN_STRETCH,_MCISTR_bool);
942 ITEM3("slow","play","rate",MCI_ANIM_GETDEVCAPS_SLOW_RATE,_MCISTR_int);
943 ITEM3("fast","play","rate",MCI_ANIM_GETDEVCAPS_FAST_RATE,_MCISTR_int);
944 ITEM3("normal","play","rate",MCI_ANIM_GETDEVCAPS_NORMAL_RATE,_MCISTR_int);
945 break;
946 case MCI_DEVTYPE_OVERLAY:
947 ITEM1("windows",MCI_OVLY_GETDEVCAPS_MAX_WINDOWS,_MCISTR_int);
948 ITEM2("can","freeze",MCI_OVLY_GETDEVCAPS_CAN_FREEZE,_MCISTR_bool);
949 ITEM2("can","stretch",MCI_OVLY_GETDEVCAPS_CAN_STRETCH,_MCISTR_bool);
950 break;
951 case MCI_DEVTYPE_VIDEODISC:
952 FLAG1("cav",MCI_VD_GETDEVCAPS_CAV);
953 FLAG1("clv",MCI_VD_GETDEVCAPS_CLV);
954 ITEM2("can","reverse",MCI_VD_GETDEVCAPS_CAN_REVERSE,_MCISTR_bool);
955 ITEM3("slow","play","rate",MCI_VD_GETDEVCAPS_SLOW_RATE,_MCISTR_int);
956 ITEM3("fast","play","rate",MCI_VD_GETDEVCAPS_FAST_RATE,_MCISTR_int);
957 ITEM3("normal","play","rate",MCI_VD_GETDEVCAPS_NORMAL_RATE,_MCISTR_int);
958 break;
959 case MCI_DEVTYPE_WAVEFORM_AUDIO:
960 ITEM1("inputs",MCI_WAVE_GETDEVCAPS_INPUTS,_MCISTR_int);
961 ITEM1("outputs",MCI_WAVE_GETDEVCAPS_OUTPUTS,_MCISTR_int);
962 break;
964 i++;
966 _MCI_CALL_DRIVER( MCI_GETDEVCAPS, MAKE_SEGPTR(&gdcParams) );
967 /* no timeformat needed */
968 if (res==0)
969 _MCISTR_convreturn(type,gdcParams.dwReturn,lpstrReturnString,uReturnLength,uDevTyp,0);
970 return res;
972 #undef ITEM1
973 #undef ITEM2
974 #undef ITEM3
975 /* resumes operation of device. no arguments, no return values */
976 static DWORD
977 MCISTR_Resume(_MCISTR_PROTO_) {
978 MCI_GENERIC_PARMS genParams;
979 int res;
981 genParams.dwCallback=0;
982 _MCI_CALL_DRIVER( MCI_RESUME, MAKE_SEGPTR(&genParams) );
983 return res;
986 /* pauses operation of device. no arguments, no return values */
987 static DWORD
988 MCISTR_Pause(_MCISTR_PROTO_) {
989 MCI_GENERIC_PARMS genParams;
990 int res;
991 genParams.dwCallback=0;
992 _MCI_CALL_DRIVER( MCI_PAUSE, MAKE_SEGPTR(&genParams) );
993 return res;
996 /* stops operation of device. no arguments, no return values */
997 static DWORD
998 MCISTR_Stop(_MCISTR_PROTO_) {
999 MCI_GENERIC_PARMS genParams;
1000 int res;
1001 genParams.dwCallback=0;
1002 _MCI_CALL_DRIVER( MCI_STOP, MAKE_SEGPTR(&genParams) );
1003 return res;
1006 /* starts recording.
1007 * Arguments:
1008 * "overwrite" overwrite existing things
1009 * "insert" insert at current position
1010 * "to <time>" record up to <time> (specified in timeformat)
1011 * "from <time>" record from <time> (specified in timeformat)
1013 static DWORD
1014 MCISTR_Record(_MCISTR_PROTO_) {
1015 int i,res,timef,nrargs,j,k,a[4];
1016 char *parsestr;
1017 MCI_RECORD_PARMS recordParams;
1019 res = _MCISTR_determine_timeformat(dev,wDevID,uDevTyp,&timef);
1020 if (res) return res;
1022 switch (timef) {
1023 case MCI_FORMAT_MILLISECONDS:
1024 case MCI_FORMAT_FRAMES:
1025 case MCI_FORMAT_BYTES:
1026 case MCI_FORMAT_SAMPLES:
1027 nrargs=1;
1028 parsestr="%d";
1029 break;
1030 case MCI_FORMAT_HMS:
1031 case MCI_FORMAT_MSF:
1032 parsestr="%d:%d:%d";
1033 nrargs=3;
1034 break;
1035 case MCI_FORMAT_TMSF:
1036 parsestr="%d:%d:%d:%d";
1037 nrargs=4;
1038 break;
1039 default:fprintf(stdnimp,"mciSendString:PLAY:unknown timeformat %d, please report.\n",timef);
1040 parsestr="%d";
1041 nrargs=1;
1042 break;
1044 recordParams.dwCallback = 0;
1045 i = 0;
1046 while (i<nrofkeywords) {
1047 if (!strcmp(keywords[i],"to") && (i+1<nrofkeywords)) {
1048 dwFlags |= MCI_TO;
1049 a[0]=a[1]=a[2]=a[3]=0;
1050 j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
1051 /* add up all integers we got, if we have more
1052 * shift them. (Well I should use the macros in
1053 * mmsystem.h, right).
1055 recordParams.dwTo=0;
1056 for (k=0;k<j;k++)
1057 recordParams.dwTo+=a[k]<<(8*(nrargs-k));
1058 i+=2;
1059 continue;
1061 if (!strcmp(keywords[i],"from") && (i+1<nrofkeywords)) {
1062 dwFlags |= MCI_FROM;
1063 a[0]=a[1]=a[2]=a[3]=0;
1064 j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
1065 /* dito. */
1066 recordParams.dwFrom=0;
1067 for (k=0;k<j;k++)
1068 recordParams.dwFrom+=a[k]<<(8*(nrargs-k));
1069 i+=2;
1070 continue;
1072 FLAG1("insert",MCI_RECORD_INSERT);
1073 FLAG1("overwrite",MCI_RECORD_OVERWRITE);
1074 i++;
1076 _MCI_CALL_DRIVER( MCI_RECORD, MAKE_SEGPTR(&recordParams) );
1077 return res;
1080 /* play media
1081 * Arguments:
1082 * "to <time>" play up to <time> (specified in set timeformat)
1083 * "from <time>" play from <time> (specified in set timeformat)
1084 * Animation:
1085 * "slow" play slow
1086 * "fast" play fast
1087 * "scan" play as fast as possible (with audio disabled perhaps)
1088 * "reverse" play reverse
1089 * "speed <fps>" play with specified frames per second
1090 * Videodisc:
1091 * "slow" play slow
1092 * "fast" play fast
1093 * "scan" play as fast as possible (with audio disabled perhaps)
1094 * "reverse" play reverse
1095 * "speed <fps>" play with specified frames per second
1097 static DWORD
1098 MCISTR_Play(_MCISTR_PROTO_) {
1099 int i,res,timef,nrargs,j,k,a[4];
1100 char *parsestr;
1101 union {
1102 MCI_PLAY_PARMS playParams;
1103 MCI_VD_PLAY_PARMS vdplayParams;
1104 MCI_ANIM_PLAY_PARMS animplayParams;
1105 } U;
1107 res = _MCISTR_determine_timeformat(dev,wDevID,uDevTyp,&timef);
1108 if (res) return res;
1109 switch (timef) {
1110 case MCI_FORMAT_MILLISECONDS:
1111 case MCI_FORMAT_FRAMES:
1112 case MCI_FORMAT_BYTES:
1113 case MCI_FORMAT_SAMPLES:
1114 nrargs=1;
1115 parsestr="%d";
1116 break;
1117 case MCI_FORMAT_HMS:
1118 case MCI_FORMAT_MSF:
1119 parsestr="%d:%d:%d";
1120 nrargs=3;
1121 break;
1122 case MCI_FORMAT_TMSF:
1123 parsestr="%d:%d:%d:%d";
1124 nrargs=4;
1125 break;
1126 default:fprintf(stdnimp,"mciSendString:PLAY:unknown timeformat %d, please report.\n",timef);
1127 parsestr="%d";
1128 nrargs=1;
1129 break;
1131 U.playParams.dwCallback=0;
1132 i=0;
1133 while (i<nrofkeywords) {
1134 if (!strcmp(keywords[i],"to") && (i+1<nrofkeywords)) {
1135 dwFlags |= MCI_TO;
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]);
1138 /* add up all integers we got, if we have more
1139 * shift them. (Well I should use the macros in
1140 * mmsystem.h, right).
1142 U.playParams.dwTo=0;
1143 for (k=0;k<j;k++)
1144 U.playParams.dwTo+=a[k]<<(8*(nrargs-k));
1145 i+=2;
1146 continue;
1148 if (!strcmp(keywords[i],"from") && (i+1<nrofkeywords)) {
1149 dwFlags |= MCI_FROM;
1150 a[0]=a[1]=a[2]=a[3]=0;
1151 j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
1152 /* dito. */
1153 U.playParams.dwFrom=0;
1154 for (k=0;k<j;k++)
1155 U.playParams.dwFrom+=a[k]<<(8*(nrargs-k));
1156 i+=2;
1157 continue;
1159 switch (uDevTyp) {
1160 case MCI_DEVTYPE_VIDEODISC:
1161 FLAG1("slow",MCI_VD_PLAY_SLOW);
1162 FLAG1("fast",MCI_VD_PLAY_FAST);
1163 FLAG1("scan",MCI_VD_PLAY_SCAN);
1164 FLAG1("reverse",MCI_VD_PLAY_REVERSE);
1165 if (!STRCMP(keywords[i],"speed") && (i+1<nrofkeywords)) {
1166 dwFlags |= MCI_VD_PLAY_SPEED;
1167 sscanf(keywords[i+1],"%ld",&(U.vdplayParams.dwSpeed));
1168 i+=2;
1169 continue;
1171 break;
1172 case MCI_DEVTYPE_ANIMATION:
1173 FLAG1("slow",MCI_ANIM_PLAY_SLOW);
1174 FLAG1("fast",MCI_ANIM_PLAY_FAST);
1175 FLAG1("scan",MCI_ANIM_PLAY_SCAN);
1176 FLAG1("reverse",MCI_ANIM_PLAY_REVERSE);
1177 if (!STRCMP(keywords[i],"speed") && (i+1<nrofkeywords)) {
1178 dwFlags |= MCI_ANIM_PLAY_SPEED;
1179 sscanf(keywords[i+1],"%ld",&(U.animplayParams.dwSpeed));
1180 i+=2;
1181 continue;
1183 break;
1185 i++;
1187 _MCI_CALL_DRIVER( MCI_PLAY, MAKE_SEGPTR(&U) );
1188 return res;
1191 /* seek to a specified position
1192 * Arguments:
1193 * "to start" seek to start of medium
1194 * "to end" seek to end of medium
1195 * "to <time>" seek to <time> specified in current timeformat
1197 static DWORD
1198 MCISTR_Seek(_MCISTR_PROTO_) {
1199 int i,res,timef,nrargs,j,k,a[4];
1200 char *parsestr;
1201 MCI_SEEK_PARMS seekParams;
1203 res = _MCISTR_determine_timeformat(dev,wDevID,uDevTyp,&timef);
1204 if (res) return res;
1205 switch (timef) {
1206 case MCI_FORMAT_MILLISECONDS:
1207 case MCI_FORMAT_FRAMES:
1208 case MCI_FORMAT_BYTES:
1209 case MCI_FORMAT_SAMPLES:
1210 nrargs=1;
1211 parsestr="%d";
1212 break;
1213 case MCI_FORMAT_HMS:
1214 case MCI_FORMAT_MSF:
1215 parsestr="%d:%d:%d";
1216 nrargs=3;
1217 break;
1218 case MCI_FORMAT_TMSF:
1219 parsestr="%d:%d:%d:%d";
1220 nrargs=4;
1221 break;
1222 default:fprintf(stdnimp,"mciSendString:SEEK:unknown timeformat %d, please report.\n",timef);
1223 parsestr="%d";
1224 nrargs=1;
1225 break;
1227 seekParams.dwCallback=0;
1228 i=0;
1229 while (i<nrofkeywords) {
1230 if ( !STRCMP(keywords[i],"to") && (i+1<nrofkeywords)) {
1231 if (!STRCMP(keywords[i+1],"start")) {
1232 dwFlags|=MCI_SEEK_TO_START;
1233 seekParams.dwTo=0;
1234 i+=2;
1235 continue;
1237 if (!STRCMP(keywords[i+1],"end")) {
1238 dwFlags|=MCI_SEEK_TO_END;
1239 seekParams.dwTo=0;
1240 i+=2;
1241 continue;
1243 dwFlags|=MCI_TO;
1244 i+=2;
1245 a[0]=a[1]=a[2]=a[3]=0;
1246 j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
1247 seekParams.dwTo=0;
1248 for (k=0;k<j;k++)
1249 seekParams.dwTo+=a[k]<<(8*(nrargs-k));
1250 continue;
1252 switch (uDevTyp) {
1253 case MCI_DEVTYPE_VIDEODISC:
1254 FLAG1("reverse",MCI_VD_SEEK_REVERSE);
1255 break;
1257 i++;
1259 _MCI_CALL_DRIVER( MCI_SEEK, MAKE_SEGPTR(&seekParams) );
1260 return res;
1263 /* close media/driver */
1264 static DWORD
1265 MCISTR_Close(_MCISTR_PROTO_) {
1266 MCI_GENERIC_PARMS closeParams;
1267 int res;
1269 _MCI_CALL_DRIVER( MCI_CLOSE, MAKE_SEGPTR(&closeParams) );
1270 return res;
1273 /* return information.
1274 * Arguments:
1275 * "product" return product name (human readable)
1276 * "file" return filename
1277 * Animation:
1278 * "text" returns text?
1279 * Overlay:
1280 * "text" returns text?
1282 static DWORD
1283 MCISTR_Info(_MCISTR_PROTO_) {
1284 MCI_INFO_PARMS infoParams;
1285 DWORD sflags;
1286 int i,res;
1288 sflags = dwFlags;
1289 i=0;while (i<nrofkeywords) {
1290 FLAG1("product",MCI_INFO_PRODUCT);
1291 FLAG1("file",MCI_INFO_FILE);
1292 switch (uDevTyp) {
1293 case MCI_DEVTYPE_ANIMATION:
1294 FLAG1("text",MCI_ANIM_INFO_TEXT);
1295 break;
1296 case MCI_DEVTYPE_OVERLAY:
1297 FLAG1("text",MCI_OVLY_INFO_TEXT);
1298 break;
1300 i++;
1302 if (dwFlags == sflags)
1303 return MCIERR_MISSING_STRING_ARGUMENT;
1304 /* MCI driver will fill in lpstrReturn, dwRetSize.
1305 * FIXME: I don't know if this is correct behaviour
1307 _MCI_CALL_DRIVER( MCI_INFO, MAKE_SEGPTR(&infoParams) );
1308 if (res==0)
1309 _MCI_STR(infoParams.lpstrReturn);
1310 return res;
1313 DWORD mciSysInfo(DWORD dwFlags,LPMCI_SYSINFO_PARMS lpParms);
1315 /* query MCI driver itself for information
1316 * Arguments:
1317 * "installname" return install name of <device> (system.ini)
1318 * "quantity" return nr of installed drivers
1319 * "open" open drivers only (additional flag)
1320 * "name <nr>" return nr of devices with <devicetyp>
1321 * "name all" return nr of all devices
1323 * FIXME: mciSysInfo() is broken I think.
1325 static DWORD
1326 MCISTR_Sysinfo(_MCISTR_PROTO_) {
1327 MCI_SYSINFO_PARMS sysinfoParams;
1328 int i,res;
1330 sysinfoParams.lpstrReturn = lpstrReturnString;
1331 sysinfoParams.dwRetSize = uReturnLength;
1332 sysinfoParams.wDeviceType = uDevTyp;
1333 i=0;
1334 while (i<nrofkeywords) {
1335 FLAG1("installname",MCI_SYSINFO_INSTALLNAME);
1336 FLAG1("quantity",MCI_SYSINFO_INSTALLNAME);
1337 FLAG1("open",MCI_SYSINFO_OPEN);
1338 if (!strcmp(keywords[i],"name") && (i+1<nrofkeywords)) {
1339 sscanf(keywords[i+1],"%ld",&(sysinfoParams.dwNumber));
1340 dwFlags |= MCI_SYSINFO_NAME;
1341 i+=2;
1342 continue;
1344 i++;
1346 res=mciSysInfo(dwFlags,&sysinfoParams);
1347 if (dwFlags & MCI_SYSINFO_QUANTITY) {
1348 char buf[100];
1350 sprintf(buf,"%ld",*(long*)PTR_SEG_TO_LIN(lpstrReturnString));
1351 _MCI_STR(buf);
1353 /* no need to copy anything back, mciSysInfo did it for us */
1354 return res;
1357 /* load file
1358 * Argument: "<filename>"
1359 * Overlay: "at <left> <top> <right> <bottom>" additional
1361 static DWORD
1362 MCISTR_Load(_MCISTR_PROTO_) {
1363 union {
1364 MCI_LOAD_PARMS loadParams;
1365 MCI_OVLY_LOAD_PARMS ovlyloadParams;
1366 } U;
1367 int i,len,res;
1368 char *s;
1369 HANDLE x;
1371 i=0;len=0;
1372 while (i<nrofkeywords) {
1373 switch (uDevTyp) {
1374 case MCI_DEVTYPE_OVERLAY:
1375 if (!STRCMP(keywords[i],"at") && (i+4<nrofkeywords)) {
1376 dwFlags |= MCI_OVLY_RECT;
1377 sscanf(keywords[i+1],"%hd",&(U.ovlyloadParams.rc.left));
1378 sscanf(keywords[i+2],"%hd",&(U.ovlyloadParams.rc.top));
1379 sscanf(keywords[i+3],"%hd",&(U.ovlyloadParams.rc.right));
1380 sscanf(keywords[i+4],"%hd",&(U.ovlyloadParams.rc.bottom));
1381 memcpy(keywords+i,keywords+(i+5),nrofkeywords-(i+5));
1382 continue;
1384 break;
1386 len+=strlen(keywords[i])+1;
1387 i++;
1389 s=(char*)xmalloc(len);
1390 *s='\0';
1391 while (i<nrofkeywords) {
1392 strcat(s,keywords[i]);
1393 i++;
1394 if (i<nrofkeywords) strcat(s," ");
1396 /* FIXME: messy, but I strongly suspect we have to use a
1397 * segmented pointer, so I am doing that
1399 x=USER_HEAP_ALLOC(len);
1400 U.loadParams.lpfilename=(LPSTR)MAKELONG(x,USER_HeapSel);
1401 strcpy(PTR_SEG_TO_LIN(U.loadParams.lpfilename),s);
1402 free(s);
1403 dwFlags |= MCI_LOAD_FILE;
1404 _MCI_CALL_DRIVER( MCI_LOAD, MAKE_SEGPTR(&U) );
1405 USER_HEAP_FREE(x);
1406 return res;
1409 /* save to file
1410 * Argument: "<filename>"
1411 * Overlay: "at <left> <top> <right> <bottom>" additional
1413 static DWORD
1414 MCISTR_Save(_MCISTR_PROTO_) {
1415 union {
1416 MCI_SAVE_PARMS saveParams;
1417 MCI_OVLY_SAVE_PARMS ovlysaveParams;
1418 } U;
1419 int i,len,res;
1420 char *s;
1421 HANDLE x;
1423 i=0;len=0;
1424 while (i<nrofkeywords) {
1425 switch (uDevTyp) {
1426 case MCI_DEVTYPE_OVERLAY:
1427 if (!STRCMP(keywords[i],"at") && (i+4<nrofkeywords)) {
1428 dwFlags |= MCI_OVLY_RECT;
1429 sscanf(keywords[i+1],"%hd",&(U.ovlysaveParams.rc.left));
1430 sscanf(keywords[i+2],"%hd",&(U.ovlysaveParams.rc.top));
1431 sscanf(keywords[i+3],"%hd",&(U.ovlysaveParams.rc.right));
1432 sscanf(keywords[i+4],"%hd",&(U.ovlysaveParams.rc.bottom));
1433 memcpy(keywords+i,keywords+(i+5),nrofkeywords-(i+5));
1434 continue;
1436 break;
1438 len+=strlen(keywords[i])+1;
1439 i++;
1441 s=(char*)xmalloc(len);
1442 *s='\0';
1443 while (i<nrofkeywords) {
1444 strcat(s,keywords[i]);
1445 i++;
1446 if (i<nrofkeywords) strcat(s," ");
1448 /* FIXME: messy, but I strongly suspect we have to use a
1449 * segmented pointer, so I am doing that
1451 x=USER_HEAP_ALLOC(len);
1452 U.saveParams.lpfilename=(LPSTR)MAKELONG(x,USER_HeapSel);
1453 strcpy(PTR_SEG_TO_LIN(U.saveParams.lpfilename),s);
1454 free(s);
1455 dwFlags |= MCI_LOAD_FILE;
1456 _MCI_CALL_DRIVER( MCI_SAVE, MAKE_SEGPTR(&U) );
1457 USER_HEAP_FREE(x);
1458 return res;
1461 /* prepare device for input/output
1462 * (only applyable to waveform audio)
1464 static DWORD
1465 MCISTR_Cue(_MCISTR_PROTO_) {
1466 MCI_GENERIC_PARMS cueParams;
1467 int i,res;
1469 i=0;
1470 while (i<nrofkeywords) {
1471 switch (uDevTyp) {
1472 case MCI_DEVTYPE_WAVEFORM_AUDIO:
1473 FLAG1("input",MCI_WAVE_INPUT);
1474 FLAG1("output",MCI_WAVE_OUTPUT);
1475 break;
1477 i++;
1479 _MCI_CALL_DRIVER( MCI_CUE, MAKE_SEGPTR(&cueParams) );
1480 return res;
1483 /* delete information */
1484 static DWORD
1485 MCISTR_Delete(_MCISTR_PROTO_) {
1486 int timef,nrargs,i,j,k,a[4],res;
1487 char *parsestr;
1488 MCI_WAVE_DELETE_PARMS deleteParams;
1490 /* only implemented for waveform audio */
1491 if (uDevTyp != MCI_DEVTYPE_WAVEFORM_AUDIO)
1492 return MCIERR_UNSUPPORTED_FUNCTION; /* well it fits */
1493 res = _MCISTR_determine_timeformat(dev,wDevID,uDevTyp,&timef);
1494 if (res) return res;
1495 switch (timef) {
1496 case MCI_FORMAT_MILLISECONDS:
1497 case MCI_FORMAT_FRAMES:
1498 case MCI_FORMAT_BYTES:
1499 case MCI_FORMAT_SAMPLES:
1500 nrargs=1;
1501 parsestr="%d";
1502 break;
1503 case MCI_FORMAT_HMS:
1504 case MCI_FORMAT_MSF:
1505 parsestr="%d:%d:%d";
1506 nrargs=3;
1507 break;
1508 case MCI_FORMAT_TMSF:
1509 parsestr="%d:%d:%d:%d";
1510 nrargs=4;
1511 break;
1512 default:fprintf(stdnimp,"mciSendString:DELETE:unknown timeformat %d, please report.\n",timef);
1513 parsestr="%d";
1514 nrargs=1;
1515 break;
1517 i=0;
1518 while (i<nrofkeywords) {
1519 if (!strcmp(keywords[i],"to") && (i+1<nrofkeywords)) {
1520 dwFlags |= MCI_TO;
1521 a[0]=a[1]=a[2]=a[3]=0;
1522 j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
1523 /* add up all integers we got, if we have more
1524 * shift them. (Well I should use the macros in
1525 * mmsystem.h, right).
1527 deleteParams.dwTo=0;
1528 for (k=0;k<j;k++)
1529 deleteParams.dwTo+=a[k]<<(8*(nrargs-k));
1530 i+=2;
1531 continue;
1533 if (!strcmp(keywords[i],"from") && (i+1<nrofkeywords)) {
1534 dwFlags |= MCI_FROM;
1535 a[0]=a[1]=a[2]=a[3]=0;
1536 j=sscanf(keywords[i+1],parsestr,&a[0],&a[1],&a[2],&a[3]);
1537 /* dito. */
1538 deleteParams.dwFrom=0;
1539 for (k=0;k<j;k++)
1540 deleteParams.dwFrom+=a[k]<<(8*(nrargs-k));
1541 i+=2;
1542 continue;
1544 i++;
1546 _MCI_CALL_DRIVER( MCI_DELETE, MAKE_SEGPTR(&deleteParams) );
1547 return res;
1550 /* send command to device. only applies to videodisc */
1551 static DWORD
1552 MCISTR_Escape(_MCISTR_PROTO_) {
1553 MCI_VD_ESCAPE_PARMS escapeParams;
1554 int i,len,res;
1555 char *s;
1556 HANDLE x;
1558 if (uDevTyp != MCI_DEVTYPE_VIDEODISC)
1559 return MCIERR_UNSUPPORTED_FUNCTION;
1560 i=0;len=0;
1561 while (i<nrofkeywords) {
1562 len+=strlen(keywords[i])+1;
1563 i++;
1565 s=(char*)xmalloc(len);
1566 *s='\0';
1567 while (i<nrofkeywords) {
1568 strcat(s,keywords[i]);
1569 i++;
1570 if (i<nrofkeywords) strcat(s," ");
1572 /* FIXME: messy, but I strongly suspect we have to use a
1573 * segmented pointer, so I am doing that
1575 x=USER_HEAP_ALLOC(len);
1576 escapeParams.lpstrCommand=(LPSTR)MAKELONG(x,USER_HeapSel);
1577 strcpy(PTR_SEG_TO_LIN(escapeParams.lpstrCommand),s);
1578 free(s);
1579 dwFlags |= MCI_VD_ESCAPE_STRING;
1580 _MCI_CALL_DRIVER( MCI_ESCAPE, MAKE_SEGPTR(&escapeParams) );
1581 USER_HEAP_FREE(x);
1582 return res;
1585 /* unfreeze [part of] the overlayed video
1586 * only applyable to Overlay devices
1588 static DWORD
1589 MCISTR_Unfreeze(_MCISTR_PROTO_) {
1590 MCI_OVLY_RECT_PARMS unfreezeParams;
1591 int i,res;
1593 if (uDevTyp != MCI_DEVTYPE_OVERLAY)
1594 return MCIERR_UNSUPPORTED_FUNCTION;
1595 i=0;while (i<nrofkeywords) {
1596 if (!STRCMP(keywords[i],"at") && (i+4<nrofkeywords)) {
1597 sscanf(keywords[i+1],"%hd",&(unfreezeParams.rc.left));
1598 sscanf(keywords[i+2],"%hd",&(unfreezeParams.rc.top));
1599 sscanf(keywords[i+3],"%hd",&(unfreezeParams.rc.right));
1600 sscanf(keywords[i+4],"%hd",&(unfreezeParams.rc.bottom));
1601 dwFlags |= MCI_OVLY_RECT;
1602 i+=5;
1603 continue;
1605 i++;
1607 _MCI_CALL_DRIVER( MCI_UNFREEZE, MAKE_SEGPTR(&unfreezeParams) );
1608 return res;
1610 /* freeze [part of] the overlayed video
1611 * only applyable to Overlay devices
1613 static DWORD
1614 MCISTR_Freeze(_MCISTR_PROTO_) {
1615 MCI_OVLY_RECT_PARMS freezeParams;
1616 int i,res;
1618 if (uDevTyp != MCI_DEVTYPE_OVERLAY)
1619 return MCIERR_UNSUPPORTED_FUNCTION;
1620 i=0;while (i<nrofkeywords) {
1621 if (!STRCMP(keywords[i],"at") && (i+4<nrofkeywords)) {
1622 sscanf(keywords[i+1],"%hd",&(freezeParams.rc.left));
1623 sscanf(keywords[i+2],"%hd",&(freezeParams.rc.top));
1624 sscanf(keywords[i+3],"%hd",&(freezeParams.rc.right));
1625 sscanf(keywords[i+4],"%hd",&(freezeParams.rc.bottom));
1626 dwFlags |= MCI_OVLY_RECT;
1627 i+=5;
1628 continue;
1630 i++;
1632 _MCI_CALL_DRIVER( MCI_FREEZE, MAKE_SEGPTR(&freezeParams) );
1633 return res;
1636 /* copy parts of image to somewhere else
1637 * "source [at <left> <top> <right> <bottom>]" source is framebuffer [or rect]
1638 * "destination [at <left> <top> <right> <bottom>]" destination is framebuffer [or rect]
1639 * Overlay:
1640 * "frame [at <left> <top> <right> <bottom>]" frame is framebuffer [or rect]
1641 * where the video input is placed
1642 * "video [at <left> <top> <right> <bottom>]" video is whole video [or rect]
1643 * (defining part of input to
1644 * be displayed)
1646 * FIXME: This whole junk is passing multiple rectangles.
1647 * I don't know how to do that with the present interface.
1648 * (Means code below is broken)
1650 static DWORD
1651 MCISTR_Put(_MCISTR_PROTO_) {
1652 union {
1653 MCI_OVLY_RECT_PARMS ovlyputParams;
1654 MCI_ANIM_RECT_PARMS animputParams;
1655 } U;
1656 int i,res;
1657 i=0;while (i<nrofkeywords) {
1658 switch (uDevTyp) {
1659 case MCI_DEVTYPE_ANIMATION:
1660 FLAG1("source",MCI_ANIM_PUT_SOURCE);
1661 FLAG1("destination",MCI_ANIM_PUT_DESTINATION);
1662 if (!STRCMP(keywords[i],"at") && (i+4<nrofkeywords)) {
1663 sscanf(keywords[i+1],"%hd",&(U.animputParams.rc.left));
1664 sscanf(keywords[i+2],"%hd",&(U.animputParams.rc.top));
1665 sscanf(keywords[i+3],"%hd",&(U.animputParams.rc.right));
1666 sscanf(keywords[i+4],"%hd",&(U.animputParams.rc.bottom));
1667 dwFlags |= MCI_ANIM_RECT;
1668 i+=5;
1669 continue;
1671 break;
1672 case MCI_DEVTYPE_OVERLAY:
1673 FLAG1("source",MCI_OVLY_PUT_SOURCE);
1674 FLAG1("destination",MCI_OVLY_PUT_DESTINATION);
1675 FLAG1("video",MCI_OVLY_PUT_VIDEO);
1676 FLAG1("frame",MCI_OVLY_PUT_FRAME);
1677 if (!STRCMP(keywords[i],"at") && (i+4<nrofkeywords)) {
1678 sscanf(keywords[i+1],"%hd",&(U.ovlyputParams.rc.left));
1679 sscanf(keywords[i+2],"%hd",&(U.ovlyputParams.rc.top));
1680 sscanf(keywords[i+3],"%hd",&(U.ovlyputParams.rc.right));
1681 sscanf(keywords[i+4],"%hd",&(U.ovlyputParams.rc.bottom));
1682 dwFlags |= MCI_OVLY_RECT;
1683 i+=5;
1684 continue;
1686 break;
1688 i++;
1690 _MCI_CALL_DRIVER( MCI_PUT, MAKE_SEGPTR(&U) );
1691 return res;
1694 /* palette behaviour changing
1695 * (Animation only)
1696 * "normal" realize the palette normally
1697 * "background" realize the palette as background palette
1699 static DWORD
1700 MCISTR_Realize(_MCISTR_PROTO_) {
1701 MCI_GENERIC_PARMS realizeParams;
1702 int i,res;
1704 if (uDevTyp != MCI_DEVTYPE_ANIMATION)
1705 return MCIERR_UNSUPPORTED_FUNCTION;
1706 i=0;
1707 while (i<nrofkeywords) {
1708 FLAG1("background",MCI_ANIM_REALIZE_BKGD);
1709 FLAG1("normal",MCI_ANIM_REALIZE_NORM);
1710 i++;
1712 _MCI_CALL_DRIVER( MCI_REALIZE, MAKE_SEGPTR(&realizeParams) );
1713 return res;
1716 /* videodisc spinning
1717 * "up"
1718 * "down"
1720 static DWORD
1721 MCISTR_Spin(_MCISTR_PROTO_) {
1722 MCI_GENERIC_PARMS spinParams;
1723 int i,res;
1725 if (uDevTyp != MCI_DEVTYPE_VIDEODISC)
1726 return MCIERR_UNSUPPORTED_FUNCTION;
1727 i=0;
1728 while (i<nrofkeywords) {
1729 FLAG1("up",MCI_VD_SPIN_UP);
1730 FLAG1("down",MCI_VD_SPIN_UP);
1731 i++;
1733 _MCI_CALL_DRIVER( MCI_SPIN, MAKE_SEGPTR(&spinParams) );
1734 return res;
1737 /* step single frames
1738 * "reverse" optional flag
1739 * "by <nr>" for <nr> frames
1741 static DWORD
1742 MCISTR_Step(_MCISTR_PROTO_) {
1743 union {
1744 MCI_ANIM_STEP_PARMS animstepParams;
1745 MCI_VD_STEP_PARMS vdstepParams;
1746 } U;
1747 int i,res;
1749 i=0;
1750 while (i<nrofkeywords) {
1751 switch (uDevTyp) {
1752 case MCI_DEVTYPE_ANIMATION:
1753 FLAG1("reverse",MCI_ANIM_STEP_REVERSE);
1754 if (!STRCMP(keywords[i],"by") && (i+1<nrofkeywords)) {
1755 sscanf(keywords[i+1],"%ld",&(U.animstepParams.dwFrames));
1756 dwFlags |= MCI_ANIM_STEP_FRAMES;
1757 i+=2;
1758 continue;
1760 break;
1761 case MCI_DEVTYPE_VIDEODISC:
1762 FLAG1("reverse",MCI_VD_STEP_REVERSE);
1763 if (!STRCMP(keywords[i],"by") && (i+1<nrofkeywords)) {
1764 sscanf(keywords[i+1],"%ld",&(U.vdstepParams.dwFrames));
1765 dwFlags |= MCI_VD_STEP_FRAMES;
1766 i+=2;
1767 continue;
1769 break;
1771 i++;
1773 _MCI_CALL_DRIVER( MCI_STEP, MAKE_SEGPTR(&U) );
1774 return res;
1777 /* update animation window
1778 * Arguments:
1779 * "at <left> <top> <right> <bottom>" only in this rectangle
1780 * "hdc" device context
1782 static DWORD
1783 MCISTR_Update(_MCISTR_PROTO_) {
1784 int i,res;
1785 MCI_ANIM_UPDATE_PARMS updateParams;
1787 i=0;
1788 while (i<nrofkeywords) {
1789 if (!STRCMP(keywords[i],"at") && (i+4<nrofkeywords)) {
1790 sscanf(keywords[i+1],"%hd",&(updateParams.rc.left));
1791 sscanf(keywords[i+2],"%hd",&(updateParams.rc.top));
1792 sscanf(keywords[i+3],"%hd",&(updateParams.rc.right));
1793 sscanf(keywords[i+4],"%hd",&(updateParams.rc.bottom));
1794 dwFlags |= MCI_ANIM_RECT;
1795 i+=5;
1796 continue;
1798 if (!STRCMP(keywords[i],"hdc") && (i+1<nrofkeywords)) {
1799 dwFlags |= MCI_ANIM_UPDATE_HDC;
1800 sscanf(keywords[i+1],"%hd",&(updateParams.hDC));
1801 i+=2;
1802 continue;
1804 i++;
1806 _MCI_CALL_DRIVER( MCI_UPDATE, MAKE_SEGPTR(&updateParams) );
1807 return res;
1810 /* where command for animation and overlay drivers.
1811 * just returns the specified rectangle as a string
1812 * Arguments:
1813 * "source"
1814 * "destination"
1815 * Overlay special:
1816 * "video"
1817 * "frame"
1819 static DWORD
1820 MCISTR_Where(_MCISTR_PROTO_) {
1821 union {
1822 MCI_ANIM_RECT_PARMS animwhereParams;
1823 MCI_OVLY_RECT_PARMS ovlywhereParams;
1824 } U;
1825 int i,res;
1827 i=0;
1828 while (i<nrofkeywords) {
1829 switch (uDevTyp) {
1830 case MCI_DEVTYPE_ANIMATION:
1831 FLAG1("source",MCI_ANIM_WHERE_SOURCE);
1832 FLAG1("destination",MCI_ANIM_WHERE_DESTINATION);
1833 break;
1834 case MCI_DEVTYPE_OVERLAY:
1835 FLAG1("source",MCI_OVLY_WHERE_SOURCE);
1836 FLAG1("destination",MCI_OVLY_WHERE_DESTINATION);
1837 FLAG1("video",MCI_OVLY_WHERE_VIDEO);
1838 FLAG1("frame",MCI_OVLY_WHERE_FRAME);
1839 break;
1841 i++;
1843 _MCI_CALL_DRIVER( MCI_WHERE, MAKE_SEGPTR(&U) );
1844 if (res==0) {
1845 char buf[100];
1846 switch (uDevTyp) {
1847 case MCI_DEVTYPE_ANIMATION:
1848 sprintf(buf,"%d %d %d %d",
1849 U.animwhereParams.rc.left,
1850 U.animwhereParams.rc.top,
1851 U.animwhereParams.rc.right,
1852 U.animwhereParams.rc.bottom
1854 break;
1855 case MCI_DEVTYPE_OVERLAY:
1856 sprintf(buf,"%d %d %d %d",
1857 U.ovlywhereParams.rc.left,
1858 U.ovlywhereParams.rc.top,
1859 U.ovlywhereParams.rc.right,
1860 U.ovlywhereParams.rc.bottom
1862 break;
1863 default:strcpy(buf,"0 0 0 0");break;
1865 _MCI_STR(buf);
1867 return res;
1870 static DWORD
1871 MCISTR_Window(_MCISTR_PROTO_) {
1872 int i,res;
1873 char *s;
1874 union {
1875 MCI_ANIM_WINDOW_PARMS animwindowParams;
1876 MCI_OVLY_WINDOW_PARMS ovlywindowParams;
1877 } U;
1879 s=NULL;
1880 i=0;
1881 while (i<nrofkeywords) {
1882 switch (uDevTyp) {
1883 case MCI_DEVTYPE_ANIMATION:
1884 if (!STRCMP(keywords[i],"handle") && (i+1<nrofkeywords)) {
1885 dwFlags |= MCI_ANIM_WINDOW_HWND;
1886 if (!STRCMP(keywords[i+1],"default"))
1887 U.animwindowParams.hWnd = MCI_OVLY_WINDOW_DEFAULT;
1888 else
1889 sscanf(keywords[i+1],"%hd",&(U.animwindowParams.hWnd));
1890 i+=2;
1891 continue;
1893 if (!STRCMP(keywords[i],"state") && (i+1<nrofkeywords)) {
1894 dwFlags |= MCI_ANIM_WINDOW_STATE;
1895 if (!STRCMP(keywords[i+1],"hide"))
1896 U.animwindowParams.nCmdShow = SW_HIDE;
1897 if (!STRCMP(keywords[i+1],"iconic"))
1898 U.animwindowParams.nCmdShow = SW_SHOWMINNOACTIVE; /* correct? */
1899 if (!STRCMP(keywords[i+1],"minimized"))
1900 U.animwindowParams.nCmdShow = SW_SHOWMINIMIZED;
1901 if (!STRCMP(keywords[i+1],"maximized"))
1902 U.animwindowParams.nCmdShow = SW_SHOWMAXIMIZED;
1903 if (!STRCMP(keywords[i+1],"minimize"))
1904 U.animwindowParams.nCmdShow = SW_MINIMIZE;
1905 if (!STRCMP(keywords[i+1],"normal"))
1906 U.animwindowParams.nCmdShow = SW_NORMAL;
1907 if (!STRCMP(keywords[i+1],"show"))
1908 U.animwindowParams.nCmdShow = SW_SHOW;
1909 if (!STRCMP(keywords[i+1],"no") && (i+2<nrofkeywords)) {
1910 if (!STRCMP(keywords[i+2],"active"))
1911 U.animwindowParams.nCmdShow = SW_SHOWNOACTIVATE;
1912 if (!STRCMP(keywords[i+2],"action"))
1913 U.animwindowParams.nCmdShow = SW_SHOWNA;/* correct?*/
1914 i++;
1916 i+=2;
1917 continue;
1919 /* text is enclosed in " ... " as it seems */
1920 if (!STRCMP(keywords[i],"text")) {
1921 char *t;
1922 int len,j,k;
1924 if (keywords[i+1][0]!='"') {
1925 i++;
1926 continue;
1928 dwFlags |= MCI_ANIM_WINDOW_TEXT;
1929 len = strlen(keywords[i+1])+1;
1930 j = i+2;
1931 while (j<nrofkeywords) {
1932 len += strlen(keywords[j])+1;
1933 if (strchr(keywords[j],'"'))
1934 break;
1935 j++;
1937 s=(char*)xmalloc(len);
1938 strcpy(s,keywords[i+1]+1);
1939 k=j;j=i+2;
1940 while (j<=k) {
1941 strcat(s," ");
1942 strcat(s,keywords[j]);
1944 if ((t=strchr(s,'"'))) *t='\0';
1945 /* FIXME: segmented pointer? */
1946 U.animwindowParams.lpstrText = s;
1947 i=k+1;
1948 continue;
1950 FLAG1("stretch",MCI_ANIM_WINDOW_ENABLE_STRETCH);
1951 break;
1952 case MCI_DEVTYPE_OVERLAY:
1953 if (!STRCMP(keywords[i],"handle") && (i+1<nrofkeywords)) {
1954 dwFlags |= MCI_OVLY_WINDOW_HWND;
1955 if (!STRCMP(keywords[i+1],"default"))
1956 U.ovlywindowParams.hWnd = MCI_OVLY_WINDOW_DEFAULT;
1957 else
1958 sscanf(keywords[i+1],"%hd",&(U.ovlywindowParams.hWnd));
1959 i+=2;
1960 continue;
1962 if (!STRCMP(keywords[i],"state") && (i+1<nrofkeywords)) {
1963 dwFlags |= MCI_OVLY_WINDOW_STATE;
1964 if (!STRCMP(keywords[i+1],"hide"))
1965 U.ovlywindowParams.nCmdShow = SW_HIDE;
1966 if (!STRCMP(keywords[i+1],"iconic"))
1967 U.ovlywindowParams.nCmdShow = SW_SHOWMINNOACTIVE; /* correct? */
1968 if (!STRCMP(keywords[i+1],"minimized"))
1969 U.ovlywindowParams.nCmdShow = SW_SHOWMINIMIZED;
1970 if (!STRCMP(keywords[i+1],"maximized"))
1971 U.ovlywindowParams.nCmdShow = SW_SHOWMAXIMIZED;
1972 if (!STRCMP(keywords[i+1],"minimize"))
1973 U.ovlywindowParams.nCmdShow = SW_MINIMIZE;
1974 if (!STRCMP(keywords[i+1],"normal"))
1975 U.ovlywindowParams.nCmdShow = SW_NORMAL;
1976 if (!STRCMP(keywords[i+1],"show"))
1977 U.ovlywindowParams.nCmdShow = SW_SHOW;
1978 if (!STRCMP(keywords[i+1],"no") && (i+2<nrofkeywords)) {
1979 if (!STRCMP(keywords[i+2],"active"))
1980 U.ovlywindowParams.nCmdShow = SW_SHOWNOACTIVATE;
1981 if (!STRCMP(keywords[i+2],"action"))
1982 U.ovlywindowParams.nCmdShow = SW_SHOWNA;/* correct?*/
1983 i++;
1985 i+=2;
1986 continue;
1988 /* text is enclosed in " ... " as it seems */
1989 if (!STRCMP(keywords[i],"text")) {
1990 char *t;
1991 int len,j,k;
1993 if (keywords[i+1][0]!='"') {
1994 i++;
1995 continue;
1997 dwFlags |= MCI_OVLY_WINDOW_TEXT;
1998 len = strlen(keywords[i+1])+1;
1999 j = i+2;
2000 while (j<nrofkeywords) {
2001 len += strlen(keywords[j])+1;
2002 if (strchr(keywords[j],'"'))
2003 break;
2004 j++;
2006 s=(char*)xmalloc(len);
2007 strcpy(s,keywords[i+1]+1);
2008 k=j;j=i+2;
2009 while (j<=k) {
2010 strcat(s," ");
2011 strcat(s,keywords[j]);
2013 if ((t=strchr(s,'"'))) *t='\0';
2014 /* FIXME: segmented pointer? */
2015 U.ovlywindowParams.lpstrText = s;
2016 i=k+1;
2017 continue;
2019 FLAG1("stretch",MCI_OVLY_WINDOW_ENABLE_STRETCH);
2020 break;
2022 i++;
2024 _MCI_CALL_DRIVER( MCI_WINDOW, MAKE_SEGPTR(&U) );
2025 if (s) free(s);
2026 return res;
2029 struct _MCISTR_cmdtable {
2030 char *cmd;
2031 DWORD (*fun)(_MCISTR_PROTO_);
2032 } MCISTR_cmdtable[]={
2033 {"break", MCISTR_Break},
2034 {"capability", MCISTR_Capability},
2035 {"close", MCISTR_Close},
2036 {"cue", MCISTR_Cue},
2037 {"delete", MCISTR_Delete},
2038 {"escape", MCISTR_Escape},
2039 {"freeze", MCISTR_Freeze},
2040 {"info", MCISTR_Info},
2041 {"load", MCISTR_Load},
2042 {"open", MCISTR_Open},
2043 {"pause", MCISTR_Pause},
2044 {"play", MCISTR_Play},
2045 {"put", MCISTR_Put},
2046 {"realize", MCISTR_Realize},
2047 {"record", MCISTR_Record},
2048 {"resume", MCISTR_Resume},
2049 {"save", MCISTR_Save},
2050 {"seek", MCISTR_Seek},
2051 {"set", MCISTR_Set},
2052 {"spin", MCISTR_Spin},
2053 {"status", MCISTR_Status},
2054 {"step", MCISTR_Step},
2055 {"stop", MCISTR_Stop},
2056 {"sysinfo", MCISTR_Sysinfo},
2057 {"unfreeze", MCISTR_Unfreeze},
2058 {"update", MCISTR_Update},
2059 {"where", MCISTR_Where},
2060 {"window", MCISTR_Window},
2061 {NULL, NULL}
2063 /**************************************************************************
2064 * mciSendString [MMSYSTEM.702]
2066 /* The usercode sends a string with a command (and flags) expressed in
2067 * words in it... We do our best to call aprobiate drivers,
2068 * and return a errorcode AND a readable string (if lpstrRS!=NULL)
2069 * Info gathered by watching cool134.exe and from Borland's mcistrwh.hlp
2071 /* FIXME: "all" is a valid devicetype and we should access all devices if
2072 * it is used. (imagine "close all"). Not implemented yet.
2074 DWORD mciSendString (LPCSTR lpstrCommand, LPSTR lpstrReturnString,
2075 UINT uReturnLength, HWND hwndCallback)
2077 char *cmd,*dev,*args,**keywords;
2078 WORD uDevTyp=0,wDevID=0;
2079 DWORD dwFlags;
2080 int res=0,i,nrofkeywords;
2082 dprintf_mci(stddeb,"mciSendString('%s', %p, %d, %X)\n", lpstrCommand,
2083 lpstrReturnString, uReturnLength, hwndCallback
2085 /* format is <command> <device> <optargs> */
2086 cmd=strdup(lpstrCommand);
2087 dev=strchr(cmd,' ');
2088 if (dev==NULL) {
2089 free(cmd);
2090 return MCIERR_MISSING_DEVICE_NAME;
2092 *dev++='\0';
2093 args=strchr(dev,' ');
2094 if (args!=NULL) *args++='\0';
2095 AnsiUpper(dev);
2096 if (args!=NULL) {
2097 char *s;
2098 i=1;/* nrofkeywords = nrofspaces+1 */
2099 s=args;
2100 while ((s=strchr(s,' '))!=NULL) i++,s++;
2101 keywords=(char**)xmalloc(sizeof(char*)*(i+2));
2102 nrofkeywords=i;
2103 s=args;i=0;
2104 while (s && i<nrofkeywords) {
2105 keywords[i++]=s;
2106 s=strchr(s,' ');
2107 if (s) *s++='\0';
2109 keywords[i]=NULL;
2110 } else {
2111 nrofkeywords=0;
2112 keywords=(char**)xmalloc(sizeof(char*));
2114 dwFlags = 0; /* default flags */
2115 for (i=0;i<nrofkeywords;) {
2116 if (!STRCMP(keywords[i],"wait")) {
2117 dwFlags |= MCI_WAIT;
2118 memcpy(keywords+i,keywords+(i+1),nrofkeywords-i-1);
2119 nrofkeywords--;
2120 continue;
2122 if (!STRCMP(keywords[i],"notify")) {
2123 /* how should we callback? I don't know. */
2124 /*dwFlags |= MCI_NOTIFY;*/
2125 memcpy(keywords+i,keywords+(i+1),nrofkeywords-i-1);
2126 nrofkeywords--;
2127 continue;
2129 i++;
2132 /* determine wDevID and uDevTyp for all commands except "open" */
2133 if (STRCMP(cmd,"open")!=0) {
2134 wDevID=0;
2135 while (1) {
2136 SEGPTR dname;
2138 dname=(SEGPTR)mciOpenDrv[wDevID].lpstrAlias;
2139 if (dname==NULL)
2140 dname=(SEGPTR)mciOpenDrv[wDevID].lpstrDeviceType;
2141 if ((dname!=NULL)&&(!STRCMP(PTR_SEG_TO_LIN(dname),dev)))
2142 break;
2143 if (++wDevID >= MAXMCIDRIVERS) {
2144 dprintf_mci(stddeb, __FILE__":mciSendString:MAXMCIDRIVERS reached!\n");
2145 free(keywords);free(cmd);
2146 return MCIERR_INTERNAL;
2149 uDevTyp=mciDrv[wDevID].wType;
2152 for (i=0;MCISTR_cmdtable[i].cmd!=NULL;i++) {
2153 if (!STRCMP(MCISTR_cmdtable[i].cmd,cmd)) {
2154 res=MCISTR_cmdtable[i].fun(
2155 wDevID,uDevTyp,lpstrReturnString,
2156 uReturnLength,dev,(LPSTR*)keywords,nrofkeywords,
2157 dwFlags
2159 break;
2162 if (MCISTR_cmdtable[i].cmd!=NULL) {
2163 free(keywords);free(cmd);
2164 return res;
2166 fprintf(stdnimp,"mciSendString('%s', %p, %u, %X) // unimplemented, please report.\n", lpstrCommand,
2167 lpstrReturnString, uReturnLength, hwndCallback
2169 free(keywords);free(cmd);
2170 return MCIERR_MISSING_COMMAND_STRING;
2172 #endif