Fixes for several bugs in which portions of the scrollbar were not
[wine/wine-kai.git] / multimedia / mcistring.c
blob1e7a100faa584a6ec0cea6a06a96ec037cd1b86c
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 /*
4 * MCI stringinterface
6 * Copyright 1995 Marcus Meissner
7 */
8 /* FIXME:
9 * + special commands of device drivers should be handled by those drivers
10 * + this current implementation does not allow commands like
11 * "capability <filename> can play" which is allowed by the MCI standard.
12 * + return value and their conversion to strings (including error codes)
13 * is not coherent with MCI standard.
14 * + digital video interface has not been throughoutfully tested
17 #include <unistd.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <fcntl.h>
21 #include <sys/ioctl.h>
22 #include <assert.h>
23 #include "multimedia.h"
24 #include "digitalv.h"
25 #include "heap.h"
26 #include "ldt.h"
27 #include "user.h"
28 #include "driver.h"
29 #include "callback.h"
30 #include "debug.h"
31 #include "xmalloc.h"
33 DEFAULT_DEBUG_CHANNEL(mci)
35 /* The reason why I just don't lowercase the keywords array in
36 * mciSendString is left as an exercise to the reader.
37 * (EP: For the blinds, like me, it's linked to file name handling
38 * which is case sensitive).
40 #define STRCMP(x, y) lstrcmpiA(x, y)
42 /* standard function parameters for all functions */
43 #define _MCISTR_PROTO_ \
44 WORD wDevID, WORD uDevTyp, LPSTR lpstrReturnString, \
45 UINT16 uReturnLength, LPCSTR dev, LPSTR* keywords, \
46 UINT16 nrofkeywords, DWORD dwFlags, HWND16 hwndCallback
48 /* copy string to return pointer including necessary checks
49 * for use in mciSendString()
51 #define _MCI_STR(s) \
52 do { \
53 TRACE(mci, "-> returns '%s'\n", s); \
54 if (lpstrReturnString) { \
55 lstrcpynA(lpstrReturnString, s, uReturnLength); \
56 TRACE(mci, "--> '%s'\n", lpstrReturnString); \
57 } \
58 } while(0)
60 /* print a DWORD in the specified timeformat */
61 static void
62 _MCISTR_printtf(char *buf, UINT16 uDevType, DWORD timef, DWORD val)
64 *buf = '\0';
65 switch (timef) {
66 case MCI_FORMAT_MILLISECONDS:
67 case MCI_FORMAT_FRAMES:
68 case MCI_FORMAT_BYTES:
69 case MCI_FORMAT_SAMPLES:
70 case MCI_VD_FORMAT_TRACK:
71 /*case MCI_SEQ_FORMAT_SONGPTR: sameas MCI_VD_FORMAT_TRACK */
72 sprintf(buf, "%ld",val);
73 break;
74 case MCI_FORMAT_HMS:
75 /* well, the macros have the same content*/
76 /*FALLTRHOUGH*/
77 case MCI_FORMAT_MSF:
78 sprintf(buf, "%d:%d:%d",
79 MCI_HMS_HOUR(val),
80 MCI_HMS_MINUTE(val),
81 MCI_HMS_SECOND(val));
82 break;
83 case MCI_FORMAT_TMSF:
84 sprintf(buf, "%d:%d:%d:%d",
85 MCI_TMSF_TRACK(val),
86 MCI_TMSF_MINUTE(val),
87 MCI_TMSF_SECOND(val),
88 MCI_TMSF_FRAME(val));
89 break;
90 default:
91 FIXME(mci, "missing timeformat for %ld, report.\n", timef);
92 strcpy(buf, "0"); /* hmm */
93 break;
95 return;
97 /* possible different return types */
98 #define _MCISTR_int 1
99 #define _MCISTR_time 2
100 #define _MCISTR_bool 3
101 #define _MCISTR_tfname 4
102 #define _MCISTR_mode 5
103 #define _MCISTR_divtype 6
104 #define _MCISTR_seqtype 7
105 #define _MCISTR_vdmtype 8
106 #define _MCISTR_devtype 9
108 static void
109 _MCISTR_convreturn(int type, DWORD dwReturn, LPSTR lpstrReturnString,
110 WORD uReturnLength, WORD uDevTyp, int timef)
112 switch (type) {
113 case _MCISTR_vdmtype:
114 switch (dwReturn) {
115 case MCI_VD_MEDIA_CLV: _MCI_STR("CLV"); break;
116 case MCI_VD_MEDIA_CAV: _MCI_STR("CAV"); break;
117 default:
118 case MCI_VD_MEDIA_OTHER:_MCI_STR("other"); break;
120 break;
121 case _MCISTR_seqtype:
122 switch (dwReturn) {
123 case MCI_SEQ_NONE: _MCI_STR("none"); break;
124 case MCI_SEQ_SMPTE: _MCI_STR("smpte"); break;
125 case MCI_SEQ_FILE: _MCI_STR("file"); break;
126 case MCI_SEQ_MIDI: _MCI_STR("midi"); break;
127 default:FIXME(mci, "missing sequencer mode %ld\n", dwReturn);
129 break;
130 case _MCISTR_mode:
131 switch (dwReturn) {
132 case MCI_MODE_NOT_READY:_MCI_STR("not ready"); break;
133 case MCI_MODE_STOP: _MCI_STR("stopped"); break;
134 case MCI_MODE_PLAY: _MCI_STR("playing"); break;
135 case MCI_MODE_RECORD: _MCI_STR("recording"); break;
136 case MCI_MODE_SEEK: _MCI_STR("seeking"); break;
137 case MCI_MODE_PAUSE: _MCI_STR("paused"); break;
138 case MCI_MODE_OPEN: _MCI_STR("open"); break;
139 default:break;
141 break;
142 case _MCISTR_bool:
143 if (dwReturn)
144 _MCI_STR("true");
145 else
146 _MCI_STR("false");
147 break;
148 case _MCISTR_int:{
149 char buf[16];
150 sprintf(buf, "%ld", dwReturn);
151 _MCI_STR(buf);
152 break;
154 case _MCISTR_time: {
155 char buf[100];
156 _MCISTR_printtf(buf, uDevTyp, timef, dwReturn);
157 _MCI_STR(buf);
158 break;
160 case _MCISTR_tfname:
161 switch (timef) {
162 case MCI_FORMAT_MILLISECONDS: _MCI_STR("milliseconds"); break;
163 case MCI_FORMAT_FRAMES: _MCI_STR("frames"); break;
164 case MCI_FORMAT_BYTES: _MCI_STR("bytes"); break;
165 case MCI_FORMAT_SAMPLES: _MCI_STR("samples"); break;
166 case MCI_FORMAT_HMS: _MCI_STR("hms"); break;
167 case MCI_FORMAT_MSF: _MCI_STR("msf"); break;
168 case MCI_FORMAT_TMSF: _MCI_STR("tmsf"); break;
169 default:
170 FIXME(mci, "missing timefmt for %d, report.\n", timef);
171 break;
173 break;
174 case _MCISTR_divtype:
175 switch (dwReturn) {
176 case MCI_SEQ_DIV_PPQN: _MCI_STR("PPQN"); break;
177 case MCI_SEQ_DIV_SMPTE_24: _MCI_STR("SMPTE 24 frame"); break;
178 case MCI_SEQ_DIV_SMPTE_25: _MCI_STR("SMPTE 25 frame"); break;
179 case MCI_SEQ_DIV_SMPTE_30: _MCI_STR("SMPTE 30 frame"); break;
180 case MCI_SEQ_DIV_SMPTE_30DROP: _MCI_STR("SMPTE 30 frame drop");break;
182 case _MCISTR_devtype:
183 switch (dwReturn) {
184 case MCI_DEVTYPE_VCR: _MCI_STR("vcr"); break;
185 case MCI_DEVTYPE_VIDEODISC: _MCI_STR("videodisc"); break;
186 case MCI_DEVTYPE_CD_AUDIO: _MCI_STR("cd audio"); break;
187 case MCI_DEVTYPE_OVERLAY: _MCI_STR("overlay"); break;
188 case MCI_DEVTYPE_DAT: _MCI_STR("dat"); break;
189 case MCI_DEVTYPE_SCANNER: _MCI_STR("scanner"); break;
190 case MCI_DEVTYPE_ANIMATION: _MCI_STR("animation"); break;
191 case MCI_DEVTYPE_DIGITAL_VIDEO: _MCI_STR("digital video"); break;
192 case MCI_DEVTYPE_OTHER: _MCI_STR("other"); break;
193 case MCI_DEVTYPE_WAVEFORM_AUDIO:_MCI_STR("waveform audio"); break;
194 case MCI_DEVTYPE_SEQUENCER: _MCI_STR("sequencer"); break;
195 default:FIXME(mci, "unknown device type %ld, report.\n",
196 dwReturn);break;
198 break;
199 default:
200 FIXME(mci, "unknown resulttype %d, report.\n", type);
201 break;
205 #define FLAG1(str, flag) \
206 if (!STRCMP(keywords[i], str)) { \
207 dwFlags |= flag; \
208 i++; \
209 continue; \
212 #define FLAG2(str1, str2, flag) \
213 if (!STRCMP(keywords[i], str1) && \
214 (i+1 < nrofkeywords) && \
215 !STRCMP(keywords[i+1], str2)) { \
216 dwFlags |= flag; \
217 i += 2; \
218 continue; \
221 /* All known subcommands are implemented in single functions to avoid
222 * bloat and a xxxx lines long mciSendString(). All commands are of the
223 * format MCISTR_Cmd(_MCISTR_PROTO_) where _MCISTR_PROTO_ is the above
224 * defined line of arguments. (This is just for easy enhanceability.)
225 * All functions return the MCIERR_ errorvalue as DWORD. Returnvalues
226 * for the calls are in lpstrReturnString (If I mention return values
227 * in function headers, I mean returnvalues in lpstrReturnString.)
228 * Integers are sprintf("%d")ed integers. Boolean values are
229 * "true" and "false".
230 * timeformat depending values are "%d" "%d:%d" "%d:%d:%d" "%d:%d:%d:%d"
231 * FIXME: is above line correct?
233 * Preceding every function is a list of implemented/known arguments.
234 * Feel free to add missing arguments.
239 * Opens the specified MCI driver.
240 * Arguments: <name>
241 * Optional:
242 * "shareable"
243 * "alias <aliasname>"
244 * "element <elementname>"
245 * Additional:
246 * waveform audio:
247 * "buffer <nrBytesPerSec>"
248 * Animation:
249 * "nostatic" increaste nr of nonstatic colours
250 * "parent <windowhandle>"
251 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
252 * "style child" WS_CHILD
253 * "style overlap" WS_OVERLAPPED
254 * "style popup" WS_POPUP
255 * Overlay:
256 * "parent <windowhandle>"
257 * "style <mask>" bitmask of WS_xxxxx (see windows.h)
258 * "style child" WS_CHILD
259 * "style overlap" WS_OVERLAPPED
260 * "style popup" WS_POPUP
261 * Returns nothing.
263 static DWORD
264 MCISTR_Open(_MCISTR_PROTO_)
266 int res, i;
267 char* s;
268 union U {
269 MCI_OPEN_PARMSA openParams;
270 MCI_WAVE_OPEN_PARMSA waveopenParams;
271 MCI_ANIM_OPEN_PARMSA animopenParams;
272 MCI_OVLY_OPEN_PARMSA ovlyopenParams;
273 MCI_DGV_OPEN_PARMSA dgvopenParams;
275 union U* pU = xmalloc(sizeof(union U));
277 pU->openParams.lpstrElementName = NULL;
278 s = strchr(dev, '!');
279 if (s != NULL) {
280 *s++ = '\0';
281 pU->openParams.lpstrElementName = strdup(s);
282 dwFlags |= MCI_OPEN_ELEMENT;
284 for (i = 0; i < nrofkeywords; ) {
285 if ((!STRCMP(keywords[i], "type")) && (i < nrofkeywords-1)) {
286 pU->openParams.lpstrElementName = strdup(dev);
287 dwFlags |= MCI_OPEN_ELEMENT;
288 dev = keywords[i+1];
289 /* FIXME: isn't there a memory leak here ? keyword+i ? */
290 memcpy(keywords+i, keywords+(i+2), (nrofkeywords-i-2) * sizeof(char*));
291 nrofkeywords -= 2;
292 i += 2;
293 continue;
295 i++;
297 CharUpperA((char*)dev);
298 uDevTyp = MCI_GetDevTypeFromString(dev);
299 if (uDevTyp == 0) {
300 free(pU->openParams.lpstrElementName);
301 free(pU);
302 return MCIERR_INVALID_DEVICE_NAME;
305 pU->openParams.dwCallback = hwndCallback;
306 pU->openParams.wDeviceID = wDevID;
307 pU->ovlyopenParams.dwStyle = 0;
308 pU->animopenParams.dwStyle = 0;
309 pU->openParams.lpstrDeviceType = strdup(dev);
310 pU->openParams.lpstrAlias = NULL;
311 dwFlags |= MCI_OPEN_TYPE;
312 for (i = 0; i < nrofkeywords; ) {
313 FLAG1("shareable", MCI_OPEN_SHAREABLE);
314 if (!STRCMP(keywords[i], "alias") && (i+1 < nrofkeywords)) {
315 dwFlags |= MCI_OPEN_ALIAS;
316 pU->openParams.lpstrAlias = strdup(keywords[i+1]);
317 i += 2;
318 continue;
320 if (!STRCMP(keywords[i], "element") && (i+1 < nrofkeywords)) {
321 dwFlags |= MCI_OPEN_ELEMENT;
322 assert(pU->openParams.lpstrElementName == NULL);
323 pU->openParams.lpstrElementName = strdup(keywords[i+1]);
324 i += 2;
325 continue;
327 switch (uDevTyp) {
328 case MCI_DEVTYPE_ANIMATION:
329 FLAG1("nostatic", MCI_ANIM_OPEN_NOSTATIC);
330 if (!STRCMP(keywords[i], "parent") && (i+1 < nrofkeywords)) {
331 dwFlags |= MCI_ANIM_OPEN_PARENT;
332 sscanf(keywords[i+1], "%u", &(pU->animopenParams.hWndParent));
333 i += 2;
334 continue;
336 if (!STRCMP(keywords[i], "style") && (i+1 < nrofkeywords)) {
337 DWORD st;
339 dwFlags |= MCI_ANIM_OPEN_WS;
340 if (!STRCMP(keywords[i+1], "popup")) {
341 pU->animopenParams.dwStyle |= WS_POPUP;
342 } else if (!STRCMP(keywords[i+1], "overlap")) {
343 pU->animopenParams.dwStyle |= WS_OVERLAPPED;
344 } else if (!STRCMP(keywords[i+1], "child")) {
345 pU->animopenParams.dwStyle |= WS_CHILD;
346 } else if (sscanf(keywords[i+1], "%ld", &st)) {
347 pU->animopenParams.dwStyle |= st;
348 } else
349 FIXME(mci, "unknown 'style' keyword %s, please report.\n", keywords[i+1]);
350 i += 2;
351 continue;
353 break;
354 case MCI_DEVTYPE_DIGITAL_VIDEO:
355 FLAG1("nostatic", MCI_ANIM_OPEN_NOSTATIC);
356 if (!STRCMP(keywords[i], "parent") && (i+1 < nrofkeywords)) {
357 dwFlags |= MCI_DGV_OPEN_PARENT;
358 sscanf(keywords[i+1], "%u", &(pU->dgvopenParams.hWndParent));
359 i += 2;
360 continue;
362 if (!STRCMP(keywords[i], "style") && (i+1 < nrofkeywords)) {
363 DWORD st;
365 dwFlags |= MCI_DGV_OPEN_WS;
366 if (!STRCMP(keywords[i+1], "popup")) {
367 pU->dgvopenParams.dwStyle |= WS_POPUP;
368 } else if (!STRCMP(keywords[i+1], "overlap")) {
369 pU->dgvopenParams.dwStyle |= WS_OVERLAPPED;
370 } else if (!STRCMP(keywords[i+1], "child")) {
371 pU->dgvopenParams.dwStyle |= WS_CHILD;
372 } else if (sscanf(keywords[i+1], "%ld", &st)) {
373 pU->dgvopenParams.dwStyle |= st;
374 } else
375 FIXME(mci, "unknown 'style' keyword %s, please report.\n", keywords[i+1]);
376 i += 2;
377 continue;
379 break;
380 case MCI_DEVTYPE_WAVEFORM_AUDIO:
381 if (!STRCMP(keywords[i], "buffer") && (i+1 < nrofkeywords)) {
382 dwFlags |= MCI_WAVE_OPEN_BUFFER;
383 sscanf(keywords[i+1], "%ld", &(pU->waveopenParams.dwBufferSeconds));
385 break;
386 case MCI_DEVTYPE_OVERLAY:
387 /* looks just like anim, but without NOSTATIC */
388 if (!STRCMP(keywords[i], "parent") && (i+1 < nrofkeywords)) {
389 dwFlags |= MCI_OVLY_OPEN_PARENT;
390 sscanf(keywords[i+1], "%u", &(pU->ovlyopenParams.hWndParent));
391 i += 2;
392 continue;
394 if (!STRCMP(keywords[i], "style") && (i+1 < nrofkeywords)) {
395 DWORD st;
397 dwFlags |= MCI_OVLY_OPEN_WS;
398 if (!STRCMP(keywords[i+1], "popup")) {
399 pU->ovlyopenParams.dwStyle |= WS_POPUP;
400 } else if (!STRCMP(keywords[i+1], "overlap")) {
401 pU->ovlyopenParams.dwStyle |= WS_OVERLAPPED;
402 } else if (!STRCMP(keywords[i+1], "child")) {
403 pU->ovlyopenParams.dwStyle |= WS_CHILD;
404 } else if (sscanf(keywords[i+1], "%ld", &st)) {
405 pU->ovlyopenParams.dwStyle |= st;
406 } else
407 FIXME(mci, "unknown 'style' keyword %s, please report.\n", keywords[i+1]);
408 i += 2;
409 continue;
411 break;
413 FIXME(mci, "unknown parameter passed %s, please report.\n",
414 keywords[i]);
415 i++;
417 res = mciSendCommandA(0, MCI_OPEN, dwFlags, (DWORD)pU);
419 free(pU->openParams.lpstrElementName);
420 free(pU->openParams.lpstrDeviceType);
421 free(pU->openParams.lpstrAlias);
422 free(pU);
423 return res;
426 /* A helper function for a lot of others ...
427 * for instance status/play/record/seek etc.
429 DWORD
430 _MCISTR_determine_timeformat(LPCSTR dev, WORD wDevID, WORD uDevTyp, int *timef)
432 int res;
433 DWORD dwFlags = MCI_STATUS_ITEM;
434 LPMCI_STATUS_PARMS statusParams = xmalloc(sizeof(MCI_STATUS_PARMS));
436 if (!statusParams) return 0;
437 statusParams->dwItem = MCI_STATUS_TIME_FORMAT;
438 statusParams->dwReturn = 0;
439 res = mciSendCommandA(wDevID, MCI_STATUS, dwFlags, (DWORD)statusParams);
441 if (res == 0) *timef = statusParams->dwReturn;
442 free(statusParams);
443 return res;
446 /* query status of MCI drivers
447 * Arguments:
448 * Required:
449 * "mode" - returns "not ready" "paused" "playing" "stopped" "open"
450 * "parked" "recording" "seeking" ....
451 * Basics:
452 * "current track" - returns current track as integer
453 * "length [track <nr>]" - returns length [of track <nr>] in current
454 * timeformat
455 * "number of tracks" - returns number of tracks as integer
456 * "position [track <nr>]" - returns position [in track <nr>] in current
457 * timeformat
458 * "ready" - checks if device is ready to play, -> bool
459 * "start position" - returns start position in timeformat
460 * "time format" - returns timeformat (list of possible values:
461 * "ms" "msf" "milliseconds" "hmsf" "tmsf" "frames"
462 * "bytes" "samples" "hms")
463 * "media present" - returns if media is present as bool
464 * Animation:
465 * "forward" - returns "true" if device is playing forwards
466 * "speed" - returns speed for device
467 * "palette handle" - returns palette handle
468 * "window handle" - returns window handle
469 * "stretch" - returns stretch bool
470 * MIDI sequencer:
471 * "division type" - ? returns "PPQN" "SMPTE 24 frame"
472 * "SMPTE 25 frame" "SMPTE 30 frame" "SMPTE 30 drop frame"
473 * "tempo" - current tempo in (PPQN? speed in frames, SMPTE*? speed in hsmf)
474 * "offset" - offset in dito.
475 * "port" - midi port as integer
476 * "slave" - slave device ("midi", "file", "none", "smpte")
477 * "master" - masterdevice (dito.)
478 * Overlay:
479 * "window handle" - see animation
480 * "stretch" - dito
481 * Video Disc:
482 * "speed" - speed as integer
483 * "forward" - returns bool (when playing forward)
484 * "side" - returns 1 or 2
485 * "media type" - returns "CAV" "CLV" "other"
486 * "disc size" - returns "8" or "12"
487 * WAVEFORM audio:
488 * "input" - base queries on input set
489 * "output" - base queries on output set
490 * "format tag" - return integer format tag
491 * "channels" - return integer nr of channels
492 * "bytespersec" - return average nr of bytes/sec
493 * "samplespersec" - return nr of samples per sec
494 * "bitspersample" - return bitspersample
495 * "alignment" - return block alignment
496 * "level" - return level?
497 * Digitalvideo:
498 * "audio"
499 * "audio alignment"
500 * "audio bitspersample"
501 * "audio breaks"
502 * "audio bytespersec"
503 * "audio input"
504 * "audio record"
505 * "audio source"
506 * "audio samplespersec"
507 * "audio stream"
508 * "bass"
509 * "bitsperpel"
510 * "brightness"
511 * "color"
512 * "contrast"
513 * "disk space drive"
514 * "file completion"
515 * "file format "
516 * "file mode"
517 * "forward"
518 * "frames skipped"
519 * "gamma"
520 * "input"
521 * "left volume"
522 * "media present"
523 * "mode"
524 * "monitor"
525 * "monitor method"
526 * "nominal"
527 * "nominal frame rate"
528 * "nominal record frame rate"
529 * "output"
530 * "palette handle"
531 * "pause mode"
532 * "play speed"
533 * "record frame rate"
534 * "reference frame"
535 * "reserved size"
536 * "right volume"
537 * "seek exactly"
538 * "sharpness"
539 * "smpte"
540 * "speed"
541 * "still file format"
542 * "tint"
543 * "treble"
544 * "unsaved"
545 * "video"
546 * "video key index"
547 * "video key color"
548 * "video record"
549 * "video source"
550 * "video source number"
551 * "video stream"
552 * "volume"
553 * "window handle"
554 * "window visible"
555 * "window minimized"
556 * "window maximized"
559 #define ITEM1(str, item, xtype) \
560 if (!STRCMP(keywords[i], str)) { \
561 pU->statusParams.dwItem = item; \
562 type = xtype; \
563 i++; \
564 continue; \
566 #define ITEM2(str1, str2, item, xtype) \
567 if ( !STRCMP(keywords[i], str1) && \
568 (i+1 < nrofkeywords) && \
569 !STRCMP(keywords[i+1], str2)) { \
570 pU->statusParams.dwItem = item; \
571 type = xtype; \
572 i += 2; \
573 continue; \
575 #define ITEM3(str1, str2, str3, item, xtype) \
576 if ( !STRCMP(keywords[i], str1) && \
577 (i+2 < nrofkeywords) && \
578 !STRCMP(keywords[i+1], str2) && \
579 !STRCMP(keywords[i+2], str3)) { \
580 pU->statusParams.dwItem = item; \
581 type = xtype; \
582 i += 3; \
583 continue; \
585 #define ITEM4(str1, str2, str3, str4, item, xtype) \
586 if ( !STRCMP(keywords[i], str1) && \
587 (i+3 < nrofkeywords) && \
588 !STRCMP(keywords[i+1], str2) && \
589 !STRCMP(keywords[i+2], str3) && \
590 !STRCMP(keywords[i+3], str4)) { \
591 pU->statusParams.dwItem = item; \
592 type = xtype; \
593 i += 4; \
594 continue; \
597 static DWORD
598 MCISTR_Status(_MCISTR_PROTO_) {
599 union U {
600 MCI_STATUS_PARMS statusParams;
601 MCI_DGV_STATUS_PARMSA dgvstatusParams;
603 union U* pU = xmalloc(sizeof(union U));
604 int type = 0, i, res, timef;
606 pU->statusParams.dwCallback = hwndCallback;
607 dwFlags |= MCI_STATUS_ITEM;
608 res = _MCISTR_determine_timeformat(dev, wDevID, uDevTyp, &timef);
609 if (res) return res;
611 pU->statusParams.dwReturn = 0;
612 pU->statusParams.dwItem = 0;
614 for (i = 0; i < nrofkeywords; ) {
615 if (!STRCMP(keywords[i], "track") && (i+1 < nrofkeywords)) {
616 sscanf(keywords[i+1], "%ld", &(pU->statusParams.dwTrack));
617 dwFlags |= MCI_TRACK;
618 i += 2;
619 continue;
621 FLAG1("start", MCI_STATUS_START);
622 /* generic things */
623 ITEM2("current", "track", MCI_STATUS_CURRENT_TRACK, _MCISTR_time);
624 ITEM2("time", "format", MCI_STATUS_TIME_FORMAT, _MCISTR_tfname);
625 ITEM1("ready", MCI_STATUS_READY, _MCISTR_bool);
626 ITEM1("mode", MCI_STATUS_MODE, _MCISTR_mode);
627 ITEM3("number", "of", "tracks", MCI_STATUS_NUMBER_OF_TRACKS, _MCISTR_int);
628 ITEM1("length", MCI_STATUS_LENGTH, _MCISTR_time);
629 ITEM1("position", MCI_STATUS_POSITION, _MCISTR_time);
630 ITEM2("media", "present", MCI_STATUS_MEDIA_PRESENT, _MCISTR_bool);
632 switch (uDevTyp) {
633 case MCI_DEVTYPE_ANIMATION:
634 ITEM2("palette", "handle", MCI_ANIM_STATUS_HPAL, _MCISTR_int);
635 ITEM2("window", "handle", MCI_ANIM_STATUS_HWND, _MCISTR_int);
636 ITEM1("stretch", MCI_ANIM_STATUS_STRETCH, _MCISTR_bool);
637 ITEM1("speed", MCI_ANIM_STATUS_SPEED, _MCISTR_int);
638 ITEM1("forward", MCI_ANIM_STATUS_FORWARD, _MCISTR_bool);
639 break;
640 case MCI_DEVTYPE_SEQUENCER:
641 /* just completing the list, not working correctly */
642 ITEM2("division", "type", MCI_SEQ_STATUS_DIVTYPE, _MCISTR_divtype);
643 /* tempo ... PPQN in frames/second, SMPTE in hmsf */
644 ITEM1("tempo", MCI_SEQ_STATUS_TEMPO, _MCISTR_int);
645 ITEM1("port", MCI_SEQ_STATUS_PORT, _MCISTR_int);
646 ITEM1("slave", MCI_SEQ_STATUS_SLAVE, _MCISTR_seqtype);
647 ITEM1("master", MCI_SEQ_STATUS_SLAVE, _MCISTR_seqtype);
648 /* offset ... PPQN in frames/second, SMPTE in hmsf */
649 ITEM1("offset", MCI_SEQ_STATUS_SLAVE, _MCISTR_time);
650 break;
651 case MCI_DEVTYPE_OVERLAY:
652 ITEM2("window", "handle", MCI_OVLY_STATUS_HWND, _MCISTR_int);
653 ITEM1("stretch", MCI_OVLY_STATUS_STRETCH, _MCISTR_bool);
654 break;
655 case MCI_DEVTYPE_VIDEODISC:
656 ITEM1("speed", MCI_VD_STATUS_SPEED, _MCISTR_int);
657 ITEM1("forward", MCI_VD_STATUS_FORWARD, _MCISTR_bool);
658 ITEM1("side", MCI_VD_STATUS_SIDE, _MCISTR_int);
659 ITEM2("media", "type", MCI_VD_STATUS_SIDE, _MCISTR_vdmtype);
660 /* returns 8 or 12 */
661 ITEM2("disc", "size", MCI_VD_STATUS_DISC_SIZE, _MCISTR_int);
662 break;
663 case MCI_DEVTYPE_WAVEFORM_AUDIO:
664 /* I am not quite sure if foll. 2 lines are right. */
665 FLAG1("input", MCI_WAVE_INPUT);
666 FLAG1("output", MCI_WAVE_OUTPUT);
668 ITEM2("format", "tag", MCI_WAVE_STATUS_FORMATTAG, _MCISTR_int);
669 ITEM1("channels", MCI_WAVE_STATUS_CHANNELS, _MCISTR_int);
670 ITEM1("bytespersec", MCI_WAVE_STATUS_AVGBYTESPERSEC, _MCISTR_int);
671 ITEM1("samplespersec", MCI_WAVE_STATUS_SAMPLESPERSEC, _MCISTR_int);
672 ITEM1("bitspersample", MCI_WAVE_STATUS_BITSPERSAMPLE, _MCISTR_int);
673 ITEM1("alignment", MCI_WAVE_STATUS_BLOCKALIGN, _MCISTR_int);
674 ITEM1("level", MCI_WAVE_STATUS_LEVEL, _MCISTR_int);
675 break;
676 case MCI_DEVTYPE_DIGITAL_VIDEO:
677 ITEM1("audio", MCI_DGV_STATUS_AUDIO, _MCISTR_bool); /* FIXME? doc says MCI_ON/MCI_OFF */
678 ITEM2("audio", "alignment", MCI_DGV_STATUS_BLOCKALIGN, _MCISTR_int);
679 ITEM2("audio", "bitspersample", MCI_DGV_STATUS_BITSPERSAMPLE, _MCISTR_int);
680 /* EPP ITEM2("audio", "breaks", MCI_AVI_STATUS_AUDIO_BREAKS, _MCISTR_int); */
681 ITEM2("audio", "bytespersec", MCI_DGV_STATUS_AVGBYTESPERSEC, _MCISTR_int);
682 ITEM2("audio", "input", MCI_DGV_STATUS_AUDIO_INPUT, _MCISTR_int);
683 ITEM2("audio", "record", MCI_DGV_STATUS_AUDIO_RECORD, _MCISTR_bool); /* FIXME? doc says MCI_ON/MCI_OFF */
684 ITEM3("audio", "source", "number", MCI_DGV_STATUS_AUDIO_SOURCE, _MCISTR_int);
685 /* FIXME: ITEM2("audio", "source", MCI_DGV_STATUS_AUDIO_SOURCE, _MCISTR_dgvaudiosource); */
686 /* EPP ITEM2("audio", "samplespersec", MCI_DGV_STATUS_SAMPLESPERSECOND, _MCISTR_int); */
687 ITEM2("audio", "stream", MCI_DGV_STATUS_AUDIO_STREAM, _MCISTR_int);
688 ITEM1("bass", MCI_DGV_STATUS_BASS, _MCISTR_int);
689 ITEM1("bitsperpel", MCI_DGV_STATUS_BITSPERPEL, _MCISTR_int);
690 ITEM1("brightness", MCI_DGV_STATUS_BRIGHTNESS, _MCISTR_int);
691 ITEM1("color", MCI_DGV_STATUS_COLOR, _MCISTR_int);
692 ITEM1("contrast", MCI_DGV_STATUS_CONTRAST, _MCISTR_int);
693 /* EPP * "disk space drive" FIXME */
694 ITEM2("file", "completion", MCI_DGV_STATUS_FILE_COMPLETION, _MCISTR_int);
695 /* EPP ITEM2("file", "format", MCI_DGV_STATUS_FILEFORMAT, _MCISTR_???); */
696 /* EPP ITEM2("file", "mode", MCI_DGV_STATUS_FILE_MODE, _MCISTR_gdvfileformat); */
697 ITEM1("forward", MCI_DGV_STATUS_FORWARD, _MCISTR_bool);
698 /* EPP ITEM2("frames", "skipped", MCI_AVI_STATUS_FRAMES_SKIPPED, _MCISTR_int); */
699 ITEM1("gamma", MCI_DGV_STATUS_GAMMA, _MCISTR_int);
700 ITEM2("input", "bass", MCI_DGV_STATUS_BASS|MCI_DGV_STATUS_INPUT, _MCISTR_int);
701 ITEM2("input", "brightness", MCI_DGV_STATUS_BRIGHTNESS|MCI_DGV_STATUS_INPUT, _MCISTR_int);
702 ITEM2("input", "color", MCI_DGV_STATUS_COLOR|MCI_DGV_STATUS_INPUT, _MCISTR_int);
703 ITEM2("input", "contrast", MCI_DGV_STATUS_CONTRAST|MCI_DGV_STATUS_INPUT, _MCISTR_int);
704 ITEM2("input", "gamma", MCI_DGV_STATUS_GAMMA|MCI_DGV_STATUS_INPUT, _MCISTR_int);
705 ITEM2("input", "sharpness", MCI_DGV_STATUS_SHARPNESS|MCI_DGV_STATUS_INPUT, _MCISTR_int);
706 ITEM2("input", "tint", MCI_DGV_STATUS_TINT|MCI_DGV_STATUS_INPUT, _MCISTR_int);
707 ITEM2("input", "treble", MCI_DGV_STATUS_TREBLE|MCI_DGV_STATUS_INPUT, _MCISTR_int);
709 ITEM2("left", "volume", MCI_DGV_STATUS_VOLUME|MCI_DGV_STATUS_LEFT, _MCISTR_int);
710 ITEM2("media", "present", MCI_STATUS_MEDIA_PRESENT, _MCISTR_bool);
711 /* EPP ITEM2("monitor", "method", MCI_DGV_STATUS_MONITOR_METHOD, _MCISTR_monitor); */
712 /* EPP ITEM1("monitor", MCI_DGV_STATUS_MONITOR, _MCISTR_monitor2); */
713 ITEM2("nominal", "bass", MCI_DGV_STATUS_BASS|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
714 ITEM2("nominal", "brightness", MCI_DGV_STATUS_BRIGHTNESS|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
715 ITEM2("nominal", "color", MCI_DGV_STATUS_COLOR|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
716 ITEM2("nominal", "contrast", MCI_DGV_STATUS_CONTRAST|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
717 ITEM2("nominal", "gamma", MCI_DGV_STATUS_GAMMA|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
718 ITEM2("nominal", "sharpness", MCI_DGV_STATUS_SHARPNESS|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
719 ITEM2("nominal", "tint", MCI_DGV_STATUS_TINT|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
720 ITEM2("nominal", "treble", MCI_DGV_STATUS_TREBLE|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
721 ITEM3("nominal", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
722 ITEM4("nominal", "record", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE|MCI_DGV_STATUS_RECORD|MCI_DGV_STATUS_NOMINAL, _MCISTR_int);
723 ITEM2("output", "bass", MCI_DGV_STATUS_BASS|MCI_DGV_STATUS_OUTPUT, _MCISTR_int);
724 ITEM2("output", "brightness", MCI_DGV_STATUS_BRIGHTNESS|MCI_DGV_STATUS_OUTPUT, _MCISTR_int);
725 ITEM2("output", "color", MCI_DGV_STATUS_COLOR|MCI_DGV_STATUS_OUTPUT, _MCISTR_int);
726 ITEM2("output", "contrast", MCI_DGV_STATUS_CONTRAST|MCI_DGV_STATUS_OUTPUT, _MCISTR_int);
727 ITEM2("output", "gamma", MCI_DGV_STATUS_GAMMA|MCI_DGV_STATUS_OUTPUT, _MCISTR_int);
728 ITEM2("output", "sharpness", MCI_DGV_STATUS_SHARPNESS|MCI_DGV_STATUS_OUTPUT, _MCISTR_int);
729 ITEM2("output", "tint", MCI_DGV_STATUS_TINT|MCI_DGV_STATUS_OUTPUT, _MCISTR_int);
730 ITEM2("output", "treble", MCI_DGV_STATUS_TREBLE|MCI_DGV_STATUS_OUTPUT, _MCISTR_int);
731 ITEM2("palette", "handle", MCI_DGV_STATUS_HPAL, _MCISTR_int); /* FIXME? */
732 ITEM2("pause", "mode", MCI_DGV_STATUS_PAUSE_MODE, _MCISTR_bool); /* FIXME */
733 /* EPP ITEM2("play", "speed", MCI_AVI_STATUS_LAST_PLAY_SPEED, _MCISTR_int); */
734 ITEM3("record", "frame", "rate", MCI_DGV_STATUS_FRAME_RATE|MCI_DGV_STATUS_RECORD, _MCISTR_int);
735 ITEM2("reference", "frame", MCI_DGV_STATUS_FRAME_RATE, _MCISTR_int); /* FIXME */
736 ITEM2("reserved", "size", MCI_DGV_STATUS_SIZE, _MCISTR_int);
737 ITEM2("right", "volume", MCI_DGV_STATUS_VOLUME|MCI_DGV_STATUS_RIGHT, _MCISTR_int);
738 ITEM2("seek", "exactly", MCI_DGV_STATUS_SEEK_EXACTLY, _MCISTR_bool);
739 ITEM1("sharpness", MCI_DGV_STATUS_SHARPNESS, _MCISTR_int);
740 /* EPP ITEM1("smpte", MCI_DGV_STATUS_SMPTE, _MCISTR_smpte); */
741 /* EPP ITEM1("speed", MCI_DGV_STATUS_SPEED, _MCISTR_speed); */
742 /* EPP ITEM3("still", "file", "format", MCI_DGV_STATUS_STILL_FILEFORMAT, _MCISTR_???); */
743 ITEM1("tint", MCI_DGV_STATUS_TINT, _MCISTR_int);
744 ITEM1("treble", MCI_DGV_STATUS_TREBLE, _MCISTR_int);
745 ITEM1("unsaved", MCI_DGV_STATUS_UNSAVED, _MCISTR_bool);
746 ITEM3("video", "key", "index", MCI_DGV_STATUS_KEY_INDEX, _MCISTR_int);
747 ITEM3("video", "key", "color", MCI_DGV_STATUS_KEY_COLOR, _MCISTR_bool);
748 ITEM2("video", "record", MCI_DGV_STATUS_VIDEO_RECORD, _MCISTR_bool); /* FIXME MCI_ON/OFF */
749 ITEM3("video", "source", "number", MCI_DGV_STATUS_VIDEO_SOURCE, _MCISTR_int);
750 /* EPP ITEM2("video", "source", MCI_DGV_STATUS_VIDEO_SOURCE, _MCISTR_videosrctype); */
751 ITEM2("video", "stream", MCI_DGV_STATUS_VIDEO_STREAM, _MCISTR_int);
752 ITEM1("video", MCI_DGV_STATUS_VIDEO, _MCISTR_bool); /* FIXME MCI_ON/OFF */
753 ITEM1("volume", MCI_DGV_STATUS_VOLUME, _MCISTR_int);
754 ITEM2("window", "handle", MCI_DGV_STATUS_HWND, _MCISTR_int);
755 ITEM2("window", "visible", MCI_DGV_STATUS_WINDOW_VISIBLE, _MCISTR_bool);
756 ITEM2("window", "minimized", MCI_DGV_STATUS_WINDOW_MINIMIZED, _MCISTR_bool);
757 ITEM2("window", "maximized",MCI_DGV_STATUS_WINDOW_MAXIMIZED , _MCISTR_bool);
758 break;
760 FIXME(mci, "unknown keyword '%s'\n", keywords[i]);
761 i++;
763 if (!pU->statusParams.dwItem)
764 return MCIERR_MISSING_STRING_ARGUMENT;
766 res = mciSendCommandA(wDevID, MCI_STATUS, dwFlags, (DWORD)pU);
768 if (res == 0)
769 _MCISTR_convreturn(type, pU->statusParams.dwReturn, lpstrReturnString, uReturnLength, uDevTyp, timef);
770 free(pU);
771 return res;
773 #undef ITEM1
774 #undef ITEM2
775 #undef ITEM3
776 #undef ITEM4
778 /* set specified parameters in respective MCI drivers
779 * Arguments:
780 * "door open" eject media or somesuch
781 * "door close" load media
782 * "time format <timeformatname>" "ms" "milliseconds" "msf" "hmsf"
783 * "tmsf" "SMPTE 24" "SMPTE 25" "SMPTE 30"
784 * "SMPTE drop 30"
785 * "audio [all|left|right] [on|off]" sets specified audiochannel on or off
786 * "video [on|off]" sets video on/off
787 * Waveform audio:
788 * "formattag pcm" sets format to pcm
789 * "formattag <nr>" sets integer formattag value
790 * "any input" accept input from any known source
791 * "any output" output to any known destination
792 * "input <nr>" input from source <nr>
793 * "output <nr>" output to destination <nr>
794 * "channels <nr>" sets nr of channels
795 * "bytespersec <nr>" sets average bytes per second
796 * "samplespersec <nr>" sets average samples per second (1 sample can
797 * be 2 bytes!)
798 * "alignment <nr>" sets the blockalignment to <nr>
799 * "bitspersample <nr>" sets the nr of bits per sample
800 * Sequencer:
801 * "master [midi|file|smpte|none]" sets the midi master device
802 * "slave [midi|file|smpte|none]" sets the midi master device
803 * "port mapper" midioutput to portmapper
804 * "port <nr>" midioutput to specified port
805 * "tempo <nr>" tempo of track (depends on timeformat/divtype)
806 * "offset <nr>" start offset?
808 static DWORD
809 MCISTR_Set(_MCISTR_PROTO_) {
810 union U {
811 MCI_SET_PARMS setParams;
812 MCI_WAVE_SET_PARMS wavesetParams;
813 MCI_SEQ_SET_PARMS seqsetParams;
815 union U* pU = xmalloc(sizeof(union U));
816 int i, res;
818 pU->setParams.dwCallback = hwndCallback;
820 for (i = 0; i < nrofkeywords; ) {
821 FLAG2("door", "open", MCI_SET_DOOR_OPEN);
822 FLAG2("door", "closed", MCI_SET_DOOR_CLOSED);
824 if (!STRCMP(keywords[i], "time") && (i+2 < nrofkeywords) && !STRCMP(keywords[i+1], "format")) {
825 dwFlags |= MCI_SET_TIME_FORMAT;
827 /* FIXME:is this a shortcut for milliseconds or
828 * minutes:seconds? */
829 if (!STRCMP(keywords[i+2], "ms"))
830 pU->setParams.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
832 if (!STRCMP(keywords[i+2], "milliseconds"))
833 pU->setParams.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
834 if (!STRCMP(keywords[i+2], "msf"))
835 pU->setParams.dwTimeFormat = MCI_FORMAT_MSF;
836 if (!STRCMP(keywords[i+2], "hms"))
837 pU->setParams.dwTimeFormat = MCI_FORMAT_HMS;
838 if (!STRCMP(keywords[i+2], "frames"))
839 pU->setParams.dwTimeFormat = MCI_FORMAT_FRAMES;
840 if (!STRCMP(keywords[i+2], "track"))
841 pU->setParams.dwTimeFormat = MCI_VD_FORMAT_TRACK;
842 if (!STRCMP(keywords[i+2], "bytes"))
843 pU->setParams.dwTimeFormat = MCI_FORMAT_BYTES;
844 if (!STRCMP(keywords[i+2], "samples"))
845 pU->setParams.dwTimeFormat = MCI_FORMAT_SAMPLES;
846 if (!STRCMP(keywords[i+2], "tmsf"))
847 pU->setParams.dwTimeFormat = MCI_FORMAT_TMSF;
848 if ( !STRCMP(keywords[i+2], "song") &&
849 (i+3 < nrofkeywords) &&
850 !STRCMP(keywords[i+3], "pointer")
852 pU->setParams.dwTimeFormat = MCI_SEQ_FORMAT_SONGPTR;
853 if (!STRCMP(keywords[i+2], "smpte") && (i+3 < nrofkeywords)) {
854 if (!STRCMP(keywords[i+3], "24"))
855 pU->setParams.dwTimeFormat = MCI_FORMAT_SMPTE_24;
856 if (!STRCMP(keywords[i+3], "25"))
857 pU->setParams.dwTimeFormat = MCI_FORMAT_SMPTE_25;
858 if (!STRCMP(keywords[i+3], "30"))
859 pU->setParams.dwTimeFormat = MCI_FORMAT_SMPTE_30;
860 if (!STRCMP(keywords[i+3], "drop") && (i+4 < nrofkeywords) && !STRCMP(keywords[i+4], "30")) {
861 pU->setParams.dwTimeFormat = MCI_FORMAT_SMPTE_30DROP;
862 i++;
864 i++;
865 /*FALLTHROUGH*/
867 i += 3;
868 continue;
870 if (!STRCMP(keywords[i], "audio") && (i+1 < nrofkeywords)) {
871 dwFlags |= MCI_SET_AUDIO;
872 if (!STRCMP(keywords[i+1], "all"))
873 pU->setParams.dwAudio = MCI_SET_AUDIO_ALL;
874 if (!STRCMP(keywords[i+1], "left"))
875 pU->setParams.dwAudio = MCI_SET_AUDIO_LEFT;
876 if (!STRCMP(keywords[i+1], "right"))
877 pU->setParams.dwAudio = MCI_SET_AUDIO_RIGHT;
878 i += 2;
879 continue;
881 FLAG1("video", MCI_SET_VIDEO);
882 FLAG1("on", MCI_SET_ON);
883 FLAG1("off", MCI_SET_OFF);
884 switch (uDevTyp) {
885 case MCI_DEVTYPE_WAVEFORM_AUDIO:
886 FLAG2("any", "input", MCI_WAVE_SET_ANYINPUT);
887 FLAG2("any", "output", MCI_WAVE_SET_ANYOUTPUT);
889 if ( !STRCMP(keywords[i], "formattag") &&
890 (i+1 < nrofkeywords) &&
891 !STRCMP(keywords[i+1], "pcm")
893 dwFlags |= MCI_WAVE_SET_FORMATTAG;
894 pU->wavesetParams.wFormatTag = WAVE_FORMAT_PCM;
895 i += 2;
896 continue;
899 /* <keyword> <integer> */
900 #define WII(str,flag,fmt,element) \
901 if (!STRCMP(keywords[i], str) && \
902 (i+1 < nrofkeywords)) { \
903 sscanf(keywords[i+1], fmt, \
904 &(pU->wavesetParams. element)); \
905 dwFlags |= flag; \
906 i += 2; \
907 continue; \
909 WII("formattag", MCI_WAVE_SET_FORMATTAG, "%u", wFormatTag);
910 WII("channels", MCI_WAVE_SET_CHANNELS, "%u", nChannels);
911 WII("bytespersec", MCI_WAVE_SET_AVGBYTESPERSEC, "%lu", nAvgBytesPerSec);
912 WII("samplespersec", MCI_WAVE_SET_SAMPLESPERSEC, "%lu", nSamplesPerSec);
913 WII("alignment", MCI_WAVE_SET_BLOCKALIGN, "%u", nBlockAlign);
914 WII("bitspersample", MCI_WAVE_SET_BITSPERSAMPLE, "%u", wBitsPerSample);
915 WII("input", MCI_WAVE_INPUT, "%u", wInput);
916 WII("output", MCI_WAVE_OUTPUT, "%u", wOutput);
917 #undef WII
918 break;
919 case MCI_DEVTYPE_SEQUENCER:
920 if (!STRCMP(keywords[i], "master") && (i+1 < nrofkeywords)) {
921 dwFlags |= MCI_SEQ_SET_MASTER;
922 if (!STRCMP(keywords[i+1], "midi"))
923 pU->seqsetParams.dwMaster = MCI_SEQ_MIDI;
924 if (!STRCMP(keywords[i+1], "file"))
925 pU->seqsetParams.dwMaster = MCI_SEQ_FILE;
926 if (!STRCMP(keywords[i+1], "smpte"))
927 pU->seqsetParams.dwMaster = MCI_SEQ_SMPTE;
928 if (!STRCMP(keywords[i+1], "none"))
929 pU->seqsetParams.dwMaster = MCI_SEQ_NONE;
930 i += 2;
931 continue;
933 if (!STRCMP(keywords[i], "slave") && (i+1 < nrofkeywords)) {
934 dwFlags |= MCI_SEQ_SET_SLAVE;
935 if (!STRCMP(keywords[i+1], "midi"))
936 pU->seqsetParams.dwMaster = MCI_SEQ_MIDI;
937 if (!STRCMP(keywords[i+1], "file"))
938 pU->seqsetParams.dwMaster = MCI_SEQ_FILE;
939 if (!STRCMP(keywords[i+1], "smpte"))
940 pU->seqsetParams.dwMaster = MCI_SEQ_SMPTE;
941 if (!STRCMP(keywords[i+1], "none"))
942 pU->seqsetParams.dwMaster = MCI_SEQ_NONE;
943 i += 2;
944 continue;
946 if ( !STRCMP(keywords[i], "port") &&
947 (i+1 < nrofkeywords) &&
948 !STRCMP(keywords[i+1], "mapper")
950 pU->seqsetParams.dwPort=-1;/* FIXME:not sure*/
951 dwFlags |= MCI_SEQ_SET_PORT;
952 i += 2;
953 continue;
955 #define SII(str,flag,element) \
956 if (!STRCMP(keywords[i], str) && \
957 (i+1 < nrofkeywords)) { \
958 sscanf(keywords[i+1], "%ld", \
959 &(pU->seqsetParams.element));\
960 dwFlags |= flag; \
961 i += 2; \
962 continue; \
964 SII("tempo", MCI_SEQ_SET_TEMPO, dwTempo);
965 SII("port", MCI_SEQ_SET_PORT, dwPort);
966 SII("offset", MCI_SEQ_SET_PORT, dwOffset);
967 #undef SII
969 i++;
971 if (!dwFlags)
972 return MCIERR_MISSING_STRING_ARGUMENT;
973 res = mciSendCommandA(wDevID, MCI_SET, dwFlags, (DWORD)pU);
974 free(pU);
975 return res;
978 /* specify break key
979 * Arguments:
980 * "off" disable break
981 * "on <keyid>" enable break on key with keyid
982 * (I strongly suspect, that there is another parameter:
983 * "window <handle>"
984 * but I don't see it mentioned in my documentation.
985 * Returns nothing.
987 static DWORD
988 MCISTR_Break(_MCISTR_PROTO_)
990 LPMCI_BREAK_PARMS breakParams = xmalloc(sizeof(MCI_BREAK_PARMS));
991 int res, i;
993 if (!breakParams) return 0;
995 breakParams->dwCallback = hwndCallback;
996 /*breakParams.hwndBreak ? */
997 for (i = 0; i < nrofkeywords; i++) {
998 FLAG1("off", MCI_BREAK_OFF);
999 if (!STRCMP(keywords[i], "on") && (nrofkeywords > i+1)) {
1000 dwFlags &= ~MCI_BREAK_OFF;
1001 dwFlags |= MCI_BREAK_KEY;
1002 sscanf(keywords[i+1], "%d", &(breakParams->nVirtKey));
1003 i += 2;
1004 continue;
1007 res = mciSendCommandA(wDevID, MCI_BREAK, dwFlags, (DWORD)breakParams);
1008 free(breakParams);
1009 return res;
1012 #define ITEM1(str, item, xtype) \
1013 if (!STRCMP(keywords[i], str)) { \
1014 gdcParams->dwItem = item; \
1015 type = xtype; \
1016 i++; \
1017 continue; \
1019 #define ITEM2(str1, str2, item, xtype) \
1020 if ( !STRCMP(keywords[i], str1) && \
1021 (i+1 < nrofkeywords) && \
1022 !STRCMP(keywords[i+1], str2)) { \
1023 gdcParams->dwItem = item; \
1024 type = xtype; \
1025 i += 2; \
1026 continue; \
1028 #define ITEM3(str1, str2, str3, item, xtype) \
1029 if ( !STRCMP(keywords[i], str1) && \
1030 (i+2 < nrofkeywords) && \
1031 !STRCMP(keywords[i+1], str2) && \
1032 !STRCMP(keywords[i+2], str3)) { \
1033 gdcParams->dwItem = item; \
1034 type = xtype; \
1035 i += 3; \
1036 continue; \
1039 /* get device capabilities of MCI drivers
1040 * Arguments:
1041 * Generic:
1042 * "device type" returns device name as string
1043 * "has audio" returns bool
1044 * "has video" returns bool
1045 * "uses files" returns bool
1046 * "compound device" returns bool
1047 * "can record" returns bool
1048 * "can play" returns bool
1049 * "can eject" returns bool
1050 * "can save" returns bool
1051 * Animation:
1052 * "palettes" returns nr of available palette entries
1053 * "windows" returns nr of available windows
1054 * "can reverse" returns bool
1055 * "can stretch" returns bool
1056 * "slow play rate" returns the slow playrate
1057 * "fast play rate" returns the fast playrate
1058 * "normal play rate" returns the normal playrate
1059 * Digital video
1060 * "can freeze" returns bool
1061 * "can lock" returns bool
1062 * "can reverse" returns bool
1063 * "can stretch" returns bool
1064 * "can stretch input" returns bool
1065 * "can test" returns bool
1066 * "has still" returns bool
1067 * "maximum play rate" returns the maximum play rate, in fps
1068 * "minimum play rate" returns the minimum play rate, in fps
1069 * "uses files" returns bool
1070 * "uses palettes" returns bool
1071 * "windows" returns nr of available windows
1072 * Overlay:
1073 * "windows" returns nr of available windows
1074 * "can stretch" returns bool
1075 * "can freeze" returns bool
1076 * Videodisc:
1077 * "cav" assume CAV discs (default if no disk inserted)
1078 * "clv" assume CLV discs
1079 * "can reverse" returns bool
1080 * "slow play rate" returns the slow playrate
1081 * "fast play rate" returns the fast playrate
1082 * "normal play rate" returns the normal playrate
1083 * Waveform audio:
1084 * "inputs" returns nr of inputdevices
1085 * "outputs" returns nr of outputdevices
1087 static DWORD
1088 MCISTR_Capability(_MCISTR_PROTO_) {
1089 MCI_GETDEVCAPS_PARMS *gdcParams = xmalloc(sizeof(MCI_GETDEVCAPS_PARMS));
1090 int type=0, i, res;
1092 gdcParams->dwCallback = hwndCallback;
1093 if (!nrofkeywords)
1094 return MCIERR_MISSING_STRING_ARGUMENT;
1095 /* well , thats default */
1096 dwFlags |= MCI_GETDEVCAPS_ITEM;
1097 gdcParams->dwItem = 0;
1099 for (i = 0; i < nrofkeywords; i++) {
1100 ITEM2("device", "type", MCI_GETDEVCAPS_DEVICE_TYPE, _MCISTR_devtype);
1101 ITEM2("has", "audio", MCI_GETDEVCAPS_HAS_AUDIO, _MCISTR_bool);
1102 ITEM2("has", "video", MCI_GETDEVCAPS_HAS_VIDEO, _MCISTR_bool);
1103 ITEM2("uses", "files", MCI_GETDEVCAPS_USES_FILES, _MCISTR_bool);
1104 ITEM2("compound", "device", MCI_GETDEVCAPS_COMPOUND_DEVICE, _MCISTR_bool);
1105 ITEM2("can", "record", MCI_GETDEVCAPS_CAN_RECORD, _MCISTR_bool);
1106 ITEM2("can", "play", MCI_GETDEVCAPS_CAN_PLAY, _MCISTR_bool);
1107 ITEM2("can", "eject", MCI_GETDEVCAPS_CAN_EJECT, _MCISTR_bool);
1108 ITEM2("can", "save", MCI_GETDEVCAPS_CAN_SAVE, _MCISTR_bool);
1109 switch (uDevTyp) {
1110 case MCI_DEVTYPE_ANIMATION:
1111 ITEM1("palettes", MCI_ANIM_GETDEVCAPS_PALETTES, _MCISTR_int);
1112 ITEM1("windows", MCI_ANIM_GETDEVCAPS_MAX_WINDOWS, _MCISTR_int);
1113 ITEM2("can", "reverse", MCI_ANIM_GETDEVCAPS_CAN_REVERSE, _MCISTR_bool);
1114 ITEM2("can", "stretch", MCI_ANIM_GETDEVCAPS_CAN_STRETCH, _MCISTR_bool);
1115 ITEM3("slow", "play", "rate", MCI_ANIM_GETDEVCAPS_SLOW_RATE, _MCISTR_int);
1116 ITEM3("fast", "play", "rate", MCI_ANIM_GETDEVCAPS_FAST_RATE, _MCISTR_int);
1117 ITEM3("normal", "play", "rate", MCI_ANIM_GETDEVCAPS_NORMAL_RATE, _MCISTR_int);
1118 break;
1119 case MCI_DEVTYPE_DIGITAL_VIDEO:
1120 ITEM2("can", "freeze", MCI_DGV_GETDEVCAPS_CAN_FREEZE, _MCISTR_bool);
1121 ITEM2("can", "lock", MCI_DGV_GETDEVCAPS_CAN_LOCK, _MCISTR_bool);
1122 ITEM2("can", "reverse", MCI_DGV_GETDEVCAPS_CAN_REVERSE, _MCISTR_bool);
1123 ITEM3("can", "stretch", "input", MCI_DGV_GETDEVCAPS_CAN_STR_IN, _MCISTR_bool);
1124 ITEM2("can", "stretch", MCI_DGV_GETDEVCAPS_CAN_STRETCH, _MCISTR_bool);
1125 ITEM2("can", "test", MCI_DGV_GETDEVCAPS_CAN_TEST, _MCISTR_bool);
1126 ITEM2("has", "still", MCI_DGV_GETDEVCAPS_HAS_STILL, _MCISTR_bool);
1127 ITEM3("maximum", "play", "rate", MCI_DGV_GETDEVCAPS_MAXIMUM_RATE, _MCISTR_int);
1128 ITEM3("minimum", "play", "rate", MCI_DGV_GETDEVCAPS_MINIMUM_RATE, _MCISTR_int);
1129 ITEM2("uses", "files", MCI_GETDEVCAPS_USES_FILES, _MCISTR_bool);
1130 ITEM2("uses", "palettes", MCI_DGV_GETDEVCAPS_PALETTES, _MCISTR_bool);
1131 ITEM1("windows", MCI_DGV_GETDEVCAPS_MAX_WINDOWS, _MCISTR_int);
1132 break;
1133 case MCI_DEVTYPE_OVERLAY:
1134 ITEM1("windows", MCI_OVLY_GETDEVCAPS_MAX_WINDOWS, _MCISTR_int);
1135 ITEM2("can", "freeze", MCI_OVLY_GETDEVCAPS_CAN_FREEZE, _MCISTR_bool);
1136 ITEM2("can", "stretch", MCI_OVLY_GETDEVCAPS_CAN_STRETCH, _MCISTR_bool);
1137 break;
1138 case MCI_DEVTYPE_VIDEODISC:
1139 FLAG1("cav", MCI_VD_GETDEVCAPS_CAV);
1140 FLAG1("clv", MCI_VD_GETDEVCAPS_CLV);
1141 ITEM2("can", "reverse", MCI_VD_GETDEVCAPS_CAN_REVERSE, _MCISTR_bool);
1142 ITEM3("slow", "play", "rate", MCI_VD_GETDEVCAPS_SLOW_RATE, _MCISTR_int);
1143 ITEM3("fast", "play", "rate", MCI_VD_GETDEVCAPS_FAST_RATE, _MCISTR_int);
1144 ITEM3("normal", "play", "rate", MCI_VD_GETDEVCAPS_NORMAL_RATE, _MCISTR_int);
1145 break;
1146 case MCI_DEVTYPE_WAVEFORM_AUDIO:
1147 ITEM1("inputs", MCI_WAVE_GETDEVCAPS_INPUTS, _MCISTR_int);
1148 ITEM1("outputs", MCI_WAVE_GETDEVCAPS_OUTPUTS, _MCISTR_int);
1149 break;
1152 res = mciSendCommandA(wDevID, MCI_GETDEVCAPS, dwFlags, (DWORD)gdcParams);
1154 /* no timeformat needed */
1155 if (res == 0)
1156 _MCISTR_convreturn(type, gdcParams->dwReturn, lpstrReturnString,
1157 uReturnLength, uDevTyp, 0);
1158 free(gdcParams);
1159 return res;
1161 #undef ITEM1
1162 #undef ITEM2
1163 #undef ITEM3
1164 /* resumes operation of device. no arguments, no return values */
1165 static DWORD
1166 MCISTR_Resume(_MCISTR_PROTO_)
1168 MCI_GENERIC_PARMS* genParams = xmalloc(sizeof(MCI_GENERIC_PARMS));
1169 int res;
1171 genParams->dwCallback = hwndCallback;
1172 res = mciSendCommandA(wDevID, MCI_RESUME, dwFlags, (DWORD)genParams);
1173 free(genParams);
1174 return res;
1177 /* pauses operation of device. no arguments, no return values */
1178 static DWORD
1179 MCISTR_Pause(_MCISTR_PROTO_)
1181 MCI_GENERIC_PARMS* genParams = xmalloc(sizeof(MCI_GENERIC_PARMS));
1182 int res;
1184 genParams->dwCallback = hwndCallback;
1185 res = mciSendCommandA(wDevID, MCI_PAUSE, dwFlags, (DWORD)genParams);
1186 free(genParams);
1187 return res;
1190 /* stops operation of device. no arguments, no return values */
1191 static DWORD
1192 MCISTR_Stop(_MCISTR_PROTO_)
1194 MCI_GENERIC_PARMS* genParams = xmalloc(sizeof(MCI_GENERIC_PARMS));
1195 int res;
1197 genParams->dwCallback = hwndCallback;
1198 res = mciSendCommandA(wDevID, MCI_STOP, dwFlags, (DWORD)genParams);
1199 free(genParams);
1200 return res;
1203 /* starts recording.
1204 * Arguments:
1205 * "overwrite" overwrite existing things
1206 * "insert" insert at current position
1207 * "to <time>" record up to <time> (specified in timeformat)
1208 * "from <time>" record from <time> (specified in timeformat)
1210 static DWORD
1211 MCISTR_Record(_MCISTR_PROTO_) {
1212 int i, res, timef, nrargs, j, k, a[4];
1213 char *parsestr;
1214 MCI_RECORD_PARMS *recordParams = xmalloc(sizeof(MCI_RECORD_PARMS));
1216 res = _MCISTR_determine_timeformat(dev, wDevID, uDevTyp, &timef);
1217 if (res) return res;
1219 switch (timef) {
1220 case MCI_FORMAT_MILLISECONDS:
1221 case MCI_FORMAT_FRAMES:
1222 case MCI_FORMAT_BYTES:
1223 case MCI_FORMAT_SAMPLES:
1224 nrargs = 1;
1225 parsestr = "%d";
1226 break;
1227 case MCI_FORMAT_HMS:
1228 case MCI_FORMAT_MSF:
1229 parsestr="%d:%d:%d";
1230 nrargs=3;
1231 break;
1232 case MCI_FORMAT_TMSF:
1233 parsestr="%d:%d:%d:%d";
1234 nrargs=4;
1235 break;
1236 default:FIXME(mci, "unknown timeformat %d, please report.\n", timef);
1237 parsestr="%d";
1238 nrargs=1;
1239 break;
1241 recordParams->dwCallback = hwndCallback;
1242 for (i = 0; i < nrofkeywords; ) {
1243 if (!strcmp(keywords[i], "to") && (i+1 < nrofkeywords)) {
1244 dwFlags |= MCI_TO;
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 /* add up all integers we got, if we have more
1248 * shift them. (Well I should use the macros in
1249 * mmsystem.h, right).
1251 recordParams->dwTo = 0;
1252 for (k = 0; k < j; k++)
1253 recordParams->dwTo += a[k] << (8*(nrargs-k));
1254 i += 2;
1255 continue;
1257 if (!strcmp(keywords[i], "from") && (i+1 < nrofkeywords)) {
1258 dwFlags |= MCI_FROM;
1259 a[0] = a[1] = a[2] = a[3] = 0;
1260 j = sscanf(keywords[i+1], parsestr, &a[0], &a[1], &a[2], &a[3]);
1261 /* dito. */
1262 recordParams->dwFrom = 0;
1263 for (k = 0; k < j; k++)
1264 recordParams->dwFrom += a[k]<<(8*(nrargs-k));
1265 i += 2;
1266 continue;
1268 FLAG1("insert", MCI_RECORD_INSERT);
1269 FLAG1("overwrite", MCI_RECORD_OVERWRITE);
1270 i++;
1272 res = mciSendCommandA(wDevID, MCI_RECORD, dwFlags, (DWORD)recordParams);
1273 free(recordParams);
1274 return res;
1277 /* play media
1278 * Arguments:
1279 * "to <time>" play up to <time> (specified in set timeformat)
1280 * "from <time>" play from <time> (specified in set timeformat)
1281 * Animation:
1282 * "slow" play slow
1283 * "fast" play fast
1284 * "scan" play as fast as possible (with audio disabled perhaps)
1285 * "reverse" play reverse
1286 * "speed <fps>" play with specified frames per second
1287 * Videodisc:
1288 * "slow" play slow
1289 * "fast" play fast
1290 * "scan" play as fast as possible (with audio disabled perhaps)
1291 * "reverse" play reverse
1292 * "speed <fps>" play with specified frames per second
1293 * Digitalvideo:
1294 * "fullscreen"
1295 * "repeat"
1296 * "reverse"
1297 * "window"
1299 static DWORD
1300 MCISTR_Play(_MCISTR_PROTO_) {
1301 int i, res, timef, nrargs, j, k, a[4];
1302 char *parsestr;
1303 union U {
1304 MCI_PLAY_PARMS playParams;
1305 MCI_VD_PLAY_PARMS vdplayParams;
1306 MCI_ANIM_PLAY_PARMS animplayParams;
1307 MCI_DGV_PLAY_PARMS dgvplayParams;
1309 union U *pU = xmalloc(sizeof(union U));
1311 res = _MCISTR_determine_timeformat(dev, wDevID, uDevTyp, &timef);
1312 if (res) return res;
1313 switch (timef) {
1314 case MCI_FORMAT_MILLISECONDS:
1315 case MCI_FORMAT_FRAMES:
1316 case MCI_FORMAT_BYTES:
1317 case MCI_FORMAT_SAMPLES:
1318 nrargs=1;
1319 parsestr="%d";
1320 break;
1321 case MCI_FORMAT_HMS:
1322 case MCI_FORMAT_MSF:
1323 parsestr="%d:%d:%d";
1324 nrargs=3;
1325 break;
1326 case MCI_FORMAT_TMSF:
1327 parsestr="%d:%d:%d:%d";
1328 nrargs=4;
1329 break;
1330 default:FIXME(mci, "unknown timeformat %d, please report.\n", timef);
1331 parsestr="%d";
1332 nrargs=1;
1333 break;
1335 pU->playParams.dwCallback = hwndCallback;
1336 for (i = 0; i < nrofkeywords; ) {
1337 if (!strcmp(keywords[i], "to") && (i+1 < nrofkeywords)) {
1338 dwFlags |= MCI_TO;
1339 a[0]=a[1]=a[2]=a[3]=0;
1340 j=sscanf(keywords[i+1], parsestr, &a[0], &a[1], &a[2], &a[3]);
1341 /* add up all integers we got, if we have more
1342 * shift them. (Well I should use the macros in
1343 * mmsystem.h, right).
1345 pU->playParams.dwTo=0;
1346 for (k = 0; k < j; k++)
1347 pU->playParams.dwTo += a[k] << (8*(nrargs-k));
1348 i += 2;
1349 continue;
1351 if (!strcmp(keywords[i], "from") && (i+1 < nrofkeywords)) {
1352 dwFlags |= MCI_FROM;
1353 a[0]=a[1]=a[2]=a[3]=0;
1354 j=sscanf(keywords[i+1], parsestr, &a[0], &a[1], &a[2], &a[3]);
1355 /* dito. */
1356 pU->playParams.dwFrom=0;
1357 for (k = 0; k < j; k++)
1358 pU->playParams.dwFrom += a[k]<<(8*(nrargs-k));
1359 i += 2;
1360 continue;
1362 switch (uDevTyp) {
1363 case MCI_DEVTYPE_VIDEODISC:
1364 FLAG1("slow", MCI_VD_PLAY_SLOW);
1365 FLAG1("fast", MCI_VD_PLAY_FAST);
1366 FLAG1("scan", MCI_VD_PLAY_SCAN);
1367 FLAG1("reverse", MCI_VD_PLAY_REVERSE);
1368 if (!STRCMP(keywords[i], "speed") && (i+1 < nrofkeywords)) {
1369 dwFlags |= MCI_VD_PLAY_SPEED;
1370 sscanf(keywords[i+1], "%ld", &(pU->vdplayParams.dwSpeed));
1371 i += 2;
1372 continue;
1374 break;
1375 case MCI_DEVTYPE_ANIMATION:
1376 FLAG1("slow", MCI_ANIM_PLAY_SLOW);
1377 FLAG1("fast", MCI_ANIM_PLAY_FAST);
1378 FLAG1("scan", MCI_ANIM_PLAY_SCAN);
1379 FLAG1("reverse", MCI_ANIM_PLAY_REVERSE);
1380 if (!STRCMP(keywords[i], "speed") && (i+1 < nrofkeywords)) {
1381 dwFlags |= MCI_ANIM_PLAY_SPEED;
1382 sscanf(keywords[i+1], "%ld", &(pU->animplayParams.dwSpeed));
1383 i += 2;
1384 continue;
1386 break;
1387 case MCI_DEVTYPE_DIGITAL_VIDEO:
1388 /* EPP FLAG1("fullscreen", MCI_MCIAVI_PLAY_FULLSCREEN); */
1389 FLAG1("repeat", MCI_DGV_PLAY_REPEAT);
1390 FLAG1("reverse", MCI_DGV_PLAY_REVERSE);
1391 /* EPP FLAG1("window", MCI_MCIAVI_PLAY_WINDOW); */
1392 break;
1394 i++;
1396 res = mciSendCommandA(wDevID, MCI_PLAY, dwFlags, (DWORD)pU);
1397 free(pU);
1398 return res;
1401 /* seek to a specified position
1402 * Arguments:
1403 * "to start" seek to start of medium
1404 * "to end" seek to end of medium
1405 * "to <time>" seek to <time> specified in current timeformat
1407 static DWORD
1408 MCISTR_Seek(_MCISTR_PROTO_) {
1409 int i, res, timef, nrargs, j, k, a[4];
1410 char *parsestr;
1411 MCI_SEEK_PARMS *seekParams = xmalloc(sizeof(MCI_SEEK_PARMS));
1413 res = _MCISTR_determine_timeformat(dev, wDevID, uDevTyp, &timef);
1414 if (res) return res;
1415 switch (timef) {
1416 case MCI_FORMAT_MILLISECONDS:
1417 case MCI_FORMAT_FRAMES:
1418 case MCI_FORMAT_BYTES:
1419 case MCI_FORMAT_SAMPLES:
1420 nrargs=1;
1421 parsestr="%d";
1422 break;
1423 case MCI_FORMAT_HMS:
1424 case MCI_FORMAT_MSF:
1425 parsestr="%d:%d:%d";
1426 nrargs=3;
1427 break;
1428 case MCI_FORMAT_TMSF:
1429 parsestr="%d:%d:%d:%d";
1430 nrargs=4;
1431 break;
1432 default:
1433 FIXME(mci, "unknown timeformat %d, please report.\n", timef);
1434 parsestr="%d";
1435 nrargs=1;
1436 break;
1438 seekParams->dwCallback = hwndCallback;
1439 for (i = 0; i < nrofkeywords; ) {
1440 if (!STRCMP(keywords[i], "to") && (i+1 < nrofkeywords)) {
1441 if (!STRCMP(keywords[i+1], "start")) {
1442 dwFlags |= MCI_SEEK_TO_START;
1443 seekParams->dwTo = 0;
1444 i += 2;
1445 continue;
1447 if (!STRCMP(keywords[i+1], "end")) {
1448 dwFlags |= MCI_SEEK_TO_END;
1449 seekParams->dwTo = 0;
1450 i += 2;
1451 continue;
1453 dwFlags |= MCI_TO;
1454 i += 2;
1455 a[0] = a[1] = a[2] = a[3] = 0;
1456 j = sscanf(keywords[i+1], parsestr, &a[0], &a[1], &a[2], &a[3]);
1457 seekParams->dwTo = 0;
1458 for (k = 0; k < j; k++)
1459 seekParams->dwTo += a[k] << (8*(nrargs-k));
1460 continue;
1462 switch (uDevTyp) {
1463 case MCI_DEVTYPE_VIDEODISC:
1464 FLAG1("reverse", MCI_VD_SEEK_REVERSE);
1465 break;
1467 i++;
1469 res = mciSendCommandA(wDevID, MCI_SEEK, dwFlags, (DWORD)seekParams);
1470 free(seekParams);
1471 return res;
1474 /* close media/driver */
1475 static DWORD
1476 MCISTR_Close(_MCISTR_PROTO_)
1478 MCI_GENERIC_PARMS* closeParams = xmalloc(sizeof(MCI_GENERIC_PARMS));
1479 int res;
1481 closeParams->dwCallback = hwndCallback;
1482 res = mciSendCommandA(wDevID, MCI_CLOSE, dwFlags, (DWORD)closeParams);
1483 free(closeParams);
1484 return res;
1487 /* return information.
1488 * Arguments:
1489 * "product" return product name (human readable)
1490 * "file" return filename
1491 * Animation:
1492 * "text" returns text?
1493 * Overlay:
1494 * "text" returns text?
1495 * Digitalvideo
1496 * "audio algorithm"
1497 * "audio quality"
1498 * "still algorithm"
1499 * "still quality"
1500 * "usage"
1501 * "version"
1502 * "video algorithm"
1503 * "video quality"
1504 * "window text"
1506 static DWORD
1507 MCISTR_Info(_MCISTR_PROTO_)
1509 union U {
1510 MCI_INFO_PARMSA infoParams;
1511 MCI_DGV_INFO_PARMSA dgvinfoParams;
1513 union U* pU = xmalloc(sizeof(union U));
1514 DWORD sflags;
1515 int i, res;
1517 sflags = dwFlags;
1518 for (i = 0; i < nrofkeywords; i++) {
1519 FLAG1("product", MCI_INFO_PRODUCT);
1520 FLAG1("file", MCI_INFO_FILE);
1521 switch (uDevTyp) {
1522 case MCI_DEVTYPE_ANIMATION:
1523 FLAG2("window", "text", MCI_ANIM_INFO_TEXT);
1524 break;
1525 case MCI_DEVTYPE_OVERLAY:
1526 FLAG2("window", "text", MCI_OVLY_INFO_TEXT);
1527 break;
1528 case MCI_DEVTYPE_DIGITAL_VIDEO:
1529 #define MI1(str, flag) \
1530 if (!STRCMP(keywords[i], str)) { \
1531 dwFlags |= MCI_DGV_INFO_ITEM; \
1532 pU->dgvinfoParams.dwItem |= flag; \
1533 i++; \
1534 continue; \
1536 #define MI2(str1, str2, flag) \
1537 if (!STRCMP(keywords[i], str1) && \
1538 (i+1 < nrofkeywords) && \
1539 !STRCMP(keywords[i+1], str2)) { \
1540 dwFlags |= MCI_DGV_INFO_ITEM; \
1541 pU->dgvinfoParams.dwItem |= flag; \
1542 i += 2; \
1543 continue; \
1545 MI2("audio", "algorithm", MCI_DGV_INFO_AUDIO_ALG);
1546 MI2("audio", "quality", MCI_DGV_INFO_AUDIO_QUALITY);
1547 MI2("still", "algorithm", MCI_DGV_INFO_STILL_ALG);
1548 MI2("still", "quality", MCI_DGV_INFO_STILL_QUALITY);
1549 MI1("usage", MCI_DGV_INFO_USAGE);
1550 MI1("version", MCI_INFO_VERSION );
1551 MI2("video", "algorithm", MCI_DGV_INFO_VIDEO_ALG);
1552 MI2("video", "quality", MCI_DGV_INFO_VIDEO_QUALITY);
1553 MI2("window", "text", MCI_DGV_INFO_TEXT);
1554 #undef MI1
1555 #undef MI2
1558 if (dwFlags == sflags)
1559 return MCIERR_MISSING_STRING_ARGUMENT;
1560 pU->infoParams.dwCallback = hwndCallback;
1562 /* MCI driver will fill in lpstrReturn, dwRetSize.
1563 * FIXME: I don't know if this is correct behaviour
1565 res = mciSendCommandA(wDevID, MCI_INFO, dwFlags, (DWORD)pU);
1566 if (res == 0)
1567 _MCI_STR(pU->infoParams.lpstrReturn);
1568 free(pU);
1569 return res;
1572 /* query MCI driver itself for information
1573 * Arguments:
1574 * "installname" return install name of <device> (system.ini)
1575 * "quantity" return nr of installed drivers
1576 * "open" open drivers only (additional flag)
1577 * "name <nr>" return nr of devices with <devicetyp>
1578 * "name all" return nr of all devices
1581 static DWORD
1582 MCISTR_Sysinfo(_MCISTR_PROTO_) {
1583 MCI_SYSINFO_PARMSA sysinfoParams;
1584 int i, res;
1586 sysinfoParams.lpstrReturn = lpstrReturnString;
1587 sysinfoParams.dwRetSize = uReturnLength;
1588 sysinfoParams.wDeviceType = uDevTyp;
1589 sysinfoParams.dwCallback = hwndCallback;
1591 for (i = 0; i < nrofkeywords; i++) {
1592 FLAG1("installname", MCI_SYSINFO_INSTALLNAME);
1593 FLAG1("quantity", MCI_SYSINFO_INSTALLNAME);
1594 FLAG1("open", MCI_SYSINFO_OPEN);
1595 if (!strcmp(keywords[i], "name") && (i+1 < nrofkeywords)) {
1596 sscanf(keywords[i+1], "%ld", &(sysinfoParams.dwNumber));
1597 dwFlags |= MCI_SYSINFO_NAME;
1598 i++;
1601 res = mciSendCommandA(0, MCI_SYSINFO, dwFlags, (DWORD)&sysinfoParams);
1603 if (dwFlags & MCI_SYSINFO_QUANTITY) {
1604 char buf[100];
1606 sprintf(buf, "%ld", *(long*)lpstrReturnString);
1607 _MCI_STR(buf);
1609 /* no need to copy anything back, mciSysInfo did it for us */
1610 return res;
1613 /* load file
1614 * Argument: "<filename>"
1615 * Overlay: "at <left> <top> <right> <bottom>" additional
1617 static DWORD
1618 MCISTR_Load(_MCISTR_PROTO_) {
1619 union U {
1620 MCI_LOAD_PARMSA loadParams;
1621 MCI_OVLY_LOAD_PARMSA ovlyloadParams;
1623 union U *pU = xmalloc(sizeof(union U));
1624 int i, len = 0, res;
1625 char *s;
1627 for (i = 0; i < nrofkeywords; ) {
1628 switch (uDevTyp) {
1629 case MCI_DEVTYPE_OVERLAY:
1630 if (!STRCMP(keywords[i], "at") && (i+4 < nrofkeywords)) {
1631 dwFlags |= MCI_OVLY_RECT;
1632 sscanf(keywords[i+1], "%d", &(pU->ovlyloadParams.rc.left));
1633 sscanf(keywords[i+2], "%d", &(pU->ovlyloadParams.rc.top));
1634 sscanf(keywords[i+3], "%d", &(pU->ovlyloadParams.rc.right));
1635 sscanf(keywords[i+4], "%d", &(pU->ovlyloadParams.rc.bottom));
1636 memcpy(keywords+i, keywords+(i+5), nrofkeywords-(i+5));
1637 continue;
1639 break;
1641 len += strlen(keywords[i])+1;
1642 i++;
1644 s=(char*)xmalloc(len);
1645 *s='\0';
1646 while (i < nrofkeywords) {
1647 strcat(s, keywords[i]);
1648 i++;
1649 if (i < nrofkeywords) strcat(s, " ");
1651 pU->loadParams.lpfilename = s;
1652 pU->loadParams.dwCallback = hwndCallback;
1653 dwFlags |= MCI_LOAD_FILE;
1654 res = mciSendCommandA(wDevID, MCI_LOAD, dwFlags, (DWORD)pU);
1655 free(s);
1656 free(pU);
1657 return res;
1660 /* save to file
1661 * Argument: "<filename>"
1662 * Overlay: "at <left> <top> <right> <bottom>" additional
1664 static DWORD
1665 MCISTR_Save(_MCISTR_PROTO_) {
1666 union U {
1667 MCI_SAVE_PARMS saveParams;
1668 MCI_OVLY_SAVE_PARMSA ovlysaveParams;
1670 union U* pU = xmalloc(sizeof(union U));
1671 int i, len = 0, res;
1672 char* s;
1674 for (i = 0; i < nrofkeywords; ) {
1675 switch (uDevTyp) {
1676 case MCI_DEVTYPE_OVERLAY:
1677 if (!STRCMP(keywords[i], "at") && (i+4 < nrofkeywords)) {
1678 dwFlags |= MCI_OVLY_RECT;
1679 sscanf(keywords[i+1], "%d", &(pU->ovlysaveParams.rc.left));
1680 sscanf(keywords[i+2], "%d", &(pU->ovlysaveParams.rc.top));
1681 sscanf(keywords[i+3], "%d", &(pU->ovlysaveParams.rc.right));
1682 sscanf(keywords[i+4], "%d", &(pU->ovlysaveParams.rc.bottom));
1683 memcpy(keywords+i, keywords+(i+5), nrofkeywords-(i+5));
1684 continue;
1686 break;
1688 len += strlen(keywords[i])+1;
1689 i++;
1691 s = (char*)xmalloc(len);
1692 *s = '\0';
1693 while (i < nrofkeywords) {
1694 strcat(s, keywords[i]);
1695 i++;
1696 if (i < nrofkeywords) strcat(s, " ");
1698 pU->saveParams.lpfilename = s;
1699 pU->saveParams.dwCallback = hwndCallback;
1700 dwFlags |= MCI_LOAD_FILE;
1701 res = mciSendCommandA(wDevID, MCI_SAVE, dwFlags, (DWORD)pU);
1702 free(s);
1703 free(pU);
1704 return res;
1707 /* prepare device for input/output
1708 * (only applyable to waveform audio)
1710 static DWORD
1711 MCISTR_Cue(_MCISTR_PROTO_) {
1712 MCI_GENERIC_PARMS *cueParams = xmalloc(sizeof(MCI_GENERIC_PARMS));
1713 int i, res;
1715 for (i = 0; i < nrofkeywords; i++) {
1716 switch (uDevTyp) {
1717 case MCI_DEVTYPE_WAVEFORM_AUDIO:
1718 FLAG1("input", MCI_WAVE_INPUT);
1719 FLAG1("output", MCI_WAVE_OUTPUT);
1720 break;
1724 cueParams->dwCallback = hwndCallback;
1726 res = mciSendCommandA(wDevID, MCI_CUE, dwFlags, (DWORD)cueParams);
1727 free(cueParams);
1728 return res;
1731 /* delete information */
1732 static DWORD
1733 MCISTR_Delete(_MCISTR_PROTO_) {
1734 int timef, nrargs, i, j, k, a[4], res;
1735 char *parsestr;
1736 MCI_WAVE_DELETE_PARMS *deleteParams = xmalloc(sizeof(MCI_WAVE_DELETE_PARMS));
1738 /* only implemented for waveform audio */
1739 if (uDevTyp != MCI_DEVTYPE_WAVEFORM_AUDIO)
1740 return MCIERR_UNSUPPORTED_FUNCTION; /* well it fits */
1741 res = _MCISTR_determine_timeformat(dev, wDevID, uDevTyp, &timef);
1742 if (res) return res;
1743 switch (timef) {
1744 case MCI_FORMAT_MILLISECONDS:
1745 case MCI_FORMAT_FRAMES:
1746 case MCI_FORMAT_BYTES:
1747 case MCI_FORMAT_SAMPLES:
1748 nrargs=1;
1749 parsestr="%d";
1750 break;
1751 case MCI_FORMAT_HMS:
1752 case MCI_FORMAT_MSF:
1753 parsestr="%d:%d:%d";
1754 nrargs=3;
1755 break;
1756 case MCI_FORMAT_TMSF:
1757 parsestr="%d:%d:%d:%d";
1758 nrargs=4;
1759 break;
1760 default:FIXME(mci, "unknown timeformat %d, please report.\n", timef);
1761 parsestr="%d";
1762 nrargs=1;
1763 break;
1765 for (i = 0; i < nrofkeywords; ) {
1766 if (!strcmp(keywords[i], "to") && (i+1 < nrofkeywords)) {
1767 dwFlags |= MCI_TO;
1768 a[0] = a[1] = a[2] = a[3] = 0;
1769 j = sscanf(keywords[i+1], parsestr, &a[0], &a[1], &a[2], &a[3]);
1770 /* add up all integers we got, if we have more
1771 * shift them. (Well I should use the macros in
1772 * mmsystem.h, right).
1774 deleteParams->dwTo = 0;
1775 for (k = 0;k < j;k++)
1776 deleteParams->dwTo += a[k]<<(8*(nrargs-k));
1777 i += 2;
1778 continue;
1780 if (!strcmp(keywords[i], "from") && (i+1 < nrofkeywords)) {
1781 dwFlags |= MCI_FROM;
1782 a[0] = a[1] = a[2] = a[3] = 0;
1783 j = sscanf(keywords[i+1], parsestr, &a[0], &a[1], &a[2], &a[3]);
1784 /* dito. */
1785 deleteParams->dwFrom = 0;
1786 for (k = 0; k < j; k++)
1787 deleteParams->dwFrom += a[k]<<(8*(nrargs-k));
1788 i += 2;
1789 continue;
1791 i++;
1793 deleteParams->dwCallback = hwndCallback;
1794 res = mciSendCommandA(wDevID, MCI_DELETE, dwFlags, (DWORD)deleteParams);
1795 free(deleteParams);
1796 return res;
1799 /* send command to device. only applies to videodisc */
1800 static DWORD
1801 MCISTR_Escape(_MCISTR_PROTO_)
1803 LPMCI_VD_ESCAPE_PARMSA escapeParams = xmalloc(sizeof(MCI_VD_ESCAPE_PARMSA));
1804 int i, len = 0, res;
1805 char *s;
1807 if (uDevTyp != MCI_DEVTYPE_VIDEODISC)
1808 return MCIERR_UNSUPPORTED_FUNCTION;
1810 for (i = 0; i < nrofkeywords; i++) {
1811 len += strlen(keywords[i]) + 1;
1813 s = (char*)malloc(len);
1814 *s = '\0';
1815 for (i = 0; i < nrofkeywords; ) {
1816 strcat(s, keywords[i]);
1817 i++;
1818 if (i < nrofkeywords) strcat(s, " ");
1820 escapeParams->lpstrCommand = s;
1821 escapeParams->dwCallback = hwndCallback;
1822 dwFlags |= MCI_VD_ESCAPE_STRING;
1823 res = mciSendCommandA(wDevID, MCI_ESCAPE, dwFlags, (DWORD)escapeParams);
1824 free(s);
1825 free(escapeParams);
1826 return res;
1829 /* unfreeze [part of] the overlayed video
1830 * only applyable to Overlay devices
1832 static DWORD
1833 MCISTR_Unfreeze(_MCISTR_PROTO_)
1835 LPMCI_OVLY_RECT_PARMS unfreezeParams = xmalloc(sizeof(MCI_OVLY_RECT_PARMS));
1836 int i, res;
1838 if (uDevTyp != MCI_DEVTYPE_OVERLAY)
1839 return MCIERR_UNSUPPORTED_FUNCTION;
1840 for (i = 0; i < nrofkeywords; ) {
1841 if (!STRCMP(keywords[i], "at") && (i+4 < nrofkeywords)) {
1842 sscanf(keywords[i+1], "%d", &(unfreezeParams->rc.left));
1843 sscanf(keywords[i+2], "%d", &(unfreezeParams->rc.top));
1844 sscanf(keywords[i+3], "%d", &(unfreezeParams->rc.right));
1845 sscanf(keywords[i+4], "%d", &(unfreezeParams->rc.bottom));
1846 dwFlags |= MCI_OVLY_RECT;
1847 i += 5;
1848 continue;
1850 i++;
1852 unfreezeParams->dwCallback = hwndCallback;
1853 res = mciSendCommandA(wDevID, MCI_UNFREEZE, dwFlags, (DWORD)unfreezeParams);
1854 free(unfreezeParams);
1855 return res;
1857 /* freeze [part of] the overlayed video
1858 * only applyable to Overlay devices
1860 static DWORD
1861 MCISTR_Freeze(_MCISTR_PROTO_)
1863 LPMCI_OVLY_RECT_PARMS freezeParams = xmalloc(sizeof(MCI_OVLY_RECT_PARMS));
1864 int i, res;
1866 if (uDevTyp != MCI_DEVTYPE_OVERLAY)
1867 return MCIERR_UNSUPPORTED_FUNCTION;
1868 for (i = 0; i < nrofkeywords; ) {
1869 if (!STRCMP(keywords[i], "at") && (i+4 < nrofkeywords)) {
1870 sscanf(keywords[i+1], "%d", &(freezeParams->rc.left));
1871 sscanf(keywords[i+2], "%d", &(freezeParams->rc.top));
1872 sscanf(keywords[i+3], "%d", &(freezeParams->rc.right));
1873 sscanf(keywords[i+4], "%d", &(freezeParams->rc.bottom));
1874 dwFlags |= MCI_OVLY_RECT;
1875 i += 5;
1876 continue;
1878 i++;
1880 freezeParams->dwCallback = hwndCallback;
1881 res = mciSendCommandA(wDevID, MCI_FREEZE, dwFlags, (DWORD)freezeParams);
1882 free(freezeParams);
1883 return res;
1886 /* copy parts of image to somewhere else
1887 * "source [at <left> <top> <right> <bottom>]" source is framebuffer [or rect]
1888 * "destination [at <left> <top> <right> <bottom>]" destination is framebuffer [or rect]
1889 * Overlay:
1890 * "frame [at <left> <top> <right> <bottom>]" frame is framebuffer [or rect]
1891 * where the video input is placed
1892 * "video [at <left> <top> <right> <bottom>]" video is whole video [or rect]
1893 * (defining part of input to
1894 * be displayed)
1895 * FIXME: This whole junk is passing multiple rectangles.
1896 * I don't know how to do that with the present interface.
1897 * (Means code below is broken)
1899 static DWORD
1900 MCISTR_Put(_MCISTR_PROTO_) {
1901 union U {
1902 MCI_OVLY_RECT_PARMS ovlyputParams;
1903 MCI_ANIM_RECT_PARMS animputParams;
1904 MCI_DGV_RECT_PARMS dgvputParams;
1906 union U* pU = xmalloc(sizeof(union U));
1907 int i, res;
1909 for (i = 0; i < nrofkeywords; ) {
1910 switch (uDevTyp) {
1911 case MCI_DEVTYPE_ANIMATION:
1912 FLAG1("source", MCI_ANIM_PUT_SOURCE);
1913 FLAG1("destination", MCI_ANIM_PUT_DESTINATION);
1914 if (!STRCMP(keywords[i], "at") && (i+4 < nrofkeywords)) {
1915 sscanf(keywords[i+1], "%d", &(pU->animputParams.rc.left));
1916 sscanf(keywords[i+2], "%d", &(pU->animputParams.rc.top));
1917 sscanf(keywords[i+3], "%d", &(pU->animputParams.rc.right));
1918 sscanf(keywords[i+4], "%d", &(pU->animputParams.rc.bottom));
1919 dwFlags |= MCI_ANIM_RECT;
1920 i += 5;
1921 continue;
1923 break;
1924 case MCI_DEVTYPE_OVERLAY:
1925 FLAG1("source", MCI_OVLY_PUT_SOURCE);
1926 FLAG1("destination", MCI_OVLY_PUT_DESTINATION);
1927 FLAG1("video", MCI_OVLY_PUT_VIDEO);
1928 FLAG1("frame", MCI_OVLY_PUT_FRAME);
1929 if (!STRCMP(keywords[i], "at") && (i+4 < nrofkeywords)) {
1930 sscanf(keywords[i+1], "%d", &(pU->ovlyputParams.rc.left));
1931 sscanf(keywords[i+2], "%d", &(pU->ovlyputParams.rc.top));
1932 sscanf(keywords[i+3], "%d", &(pU->ovlyputParams.rc.right));
1933 sscanf(keywords[i+4], "%d", &(pU->ovlyputParams.rc.bottom));
1934 dwFlags |= MCI_OVLY_RECT;
1935 i += 5;
1936 continue;
1938 break;
1939 case MCI_DEVTYPE_DIGITAL_VIDEO:
1940 FLAG1("source", MCI_DGV_PUT_SOURCE);
1941 FLAG1("destination", MCI_DGV_PUT_DESTINATION);
1942 FLAG1("video", MCI_DGV_PUT_VIDEO);
1943 FLAG1("frame", MCI_DGV_PUT_FRAME);
1944 if (!STRCMP(keywords[i], "at") && (i+4 < nrofkeywords)) {
1945 sscanf(keywords[i+1], "%d", &(pU->dgvputParams.rc.left));
1946 sscanf(keywords[i+2], "%d", &(pU->dgvputParams.rc.top));
1947 sscanf(keywords[i+3], "%d", &(pU->dgvputParams.rc.right));
1948 sscanf(keywords[i+4], "%d", &(pU->dgvputParams.rc.bottom));
1949 dwFlags |= MCI_DGV_RECT;
1950 i += 5;
1951 continue;
1953 break;
1954 break;
1956 i++;
1958 pU->dgvputParams.dwCallback = hwndCallback;
1959 res = mciSendCommandA(wDevID, MCI_PUT, dwFlags, (DWORD)pU);
1960 free(pU);
1961 return res;
1964 /* palette behaviour changing
1965 * (Animation only)
1966 * "normal" realize the palette normally
1967 * "background" realize the palette as background palette
1969 static DWORD
1970 MCISTR_Realize(_MCISTR_PROTO_)
1972 MCI_GENERIC_PARMS *realizeParams = xmalloc(sizeof(MCI_GENERIC_PARMS));
1973 int i, res;
1975 if (uDevTyp != MCI_DEVTYPE_ANIMATION)
1976 return MCIERR_UNSUPPORTED_FUNCTION;
1977 for (i = 0; i < nrofkeywords; i++) {
1978 FLAG1("background", MCI_ANIM_REALIZE_BKGD);
1979 FLAG1("normal", MCI_ANIM_REALIZE_NORM);
1981 realizeParams->dwCallback = hwndCallback;
1982 res = mciSendCommandA(wDevID, MCI_REALIZE, dwFlags, (DWORD)realizeParams);
1983 free(realizeParams);
1984 return res;
1987 /* Digitalvideo:
1988 * "algorithm <algorithm>"
1989 * "alignment to <integer>"
1990 * "bass to <factor>"
1991 * "bitspersample to <bit_count>"
1992 * "bytespersec to <integer>"
1993 * "clocktime"
1994 * "input"
1995 * "left off"
1996 * "left on"
1997 * "left volume to <factor>"
1998 * "off"
1999 * "on"
2000 * "output"
2001 * "over <duration>"
2002 * "quality <descripto>r"
2003 * "record off"
2004 * "record on"
2005 * "right off"
2006 * "right on"
2007 * "right volume to <factor>"
2008 * "samplespersec to <integer>"
2009 * "source to <sourcename>"
2010 * "stream to <number>"
2011 * "treble to <factor>"
2012 * "volume to <factor>"
2013 * Vcr:
2014 * "off"
2015 * "on"
2016 * "monitor to type number number"
2017 * "record off"
2018 * "record track track_number off"
2019 * "record on "
2020 * "record track track_number on "
2021 * "source to type number number"
2022 * "track track_number off"
2023 * "track track_number on"
2025 static DWORD
2026 MCISTR_SetAudio(_MCISTR_PROTO_)
2028 MCI_DGV_SETAUDIO_PARMSA setaudioParams;
2029 int i, res;
2031 if (uDevTyp != MCI_DEVTYPE_DIGITAL_VIDEO)
2032 return MCIERR_UNSUPPORTED_FUNCTION;
2034 setaudioParams.dwCallback = hwndCallback;
2036 for (i = 0; i < nrofkeywords; ) {
2037 if (!STRCMP(keywords[i], "algorithm") && (i+1 < nrofkeywords)) {
2038 setaudioParams.lpstrAlgorithm = strdup(keywords[i+1]);
2039 dwFlags |= MCI_DGV_SETAUDIO_ALG;
2040 i += 2;
2041 continue;
2043 #define MSAI2(str1, str2, flag) \
2044 if ( !STRCMP(keywords[i], str1) && (i+2 < nrofkeywords) && \
2045 !STRCMP(keywords[i+1], str2)) { \
2046 dwFlags |= MCI_DGV_SETAUDIO_ITEM; \
2047 setaudioParams.dwItem = flag; \
2048 sscanf(keywords[i+2], "%lu", &setaudioParams.dwValue); \
2049 i += 3; \
2050 continue; \
2052 #define MSAI3(str1, str2, str3, flag) \
2053 if ( !STRCMP(keywords[i], str1) && (i+3 < nrofkeywords) && \
2054 !STRCMP(keywords[i+1], str2) && !STRCMP(keywords[i+2], str3)) { \
2055 dwFlags |= MCI_DGV_SETAUDIO_ITEM; \
2056 setaudioParams.dwItem = flag; \
2057 sscanf(keywords[i+3], "%lu", &setaudioParams.dwValue); \
2058 i += 4; \
2059 continue; \
2061 MSAI2("alignment", "to", MCI_DGV_SETAUDIO_BLOCKALIGN);
2062 MSAI2("bass", "to", MCI_DGV_SETAUDIO_BASS);
2063 MSAI2("bitspersample", "to", MCI_DGV_SETAUDIO_BITSPERSAMPLE);
2064 MSAI2("bytespersec", "to", MCI_DGV_SETAUDIO_AVGBYTESPERSEC);
2065 MSAI2("samplespersec", "to", MCI_DGV_SETAUDIO_SAMPLESPERSEC);
2066 MSAI2("stream", "to", MCI_DGV_SETAUDIO_STREAM);
2067 MSAI2("treble", "to", MCI_DGV_SETAUDIO_TREBLE);
2068 MSAI2("volume", "to", MCI_DGV_SETAUDIO_VOLUME);
2069 MSAI3("input", "bass", "to", MCI_DGV_SETAUDIO_BASS|MCI_DGV_SETAUDIO_INPUT);
2070 MSAI3("input", "treble", "to", MCI_DGV_SETAUDIO_TREBLE|MCI_DGV_SETAUDIO_INPUT);
2071 MSAI3("input", "volume", "to", MCI_DGV_SETAUDIO_VOLUME|MCI_DGV_SETAUDIO_INPUT);
2072 MSAI3("output", "bass", "to", MCI_DGV_SETAUDIO_BASS|MCI_DGV_SETAUDIO_OUTPUT);
2073 MSAI3("output", "treble", "to", MCI_DGV_SETAUDIO_TREBLE|MCI_DGV_SETAUDIO_OUTPUT);
2074 MSAI3("output", "volume", "to", MCI_DGV_SETAUDIO_VOLUME|MCI_DGV_SETAUDIO_OUTPUT);
2076 FLAG1("clocktime", MCI_DGV_SETAUDIO_CLOCKTIME);
2077 FLAG2("left", "off", MCI_DGV_SETAUDIO_LEFT|MCI_SET_OFF);
2078 FLAG2("left", "on", MCI_DGV_SETAUDIO_LEFT|MCI_SET_ON);
2079 if (!STRCMP(keywords[i], "left") && (i+3 < nrofkeywords) &&
2080 !STRCMP(keywords[i+1], "volume") && !STRCMP(keywords[i+2], "to")) {
2081 dwFlags |= MCI_DGV_SETAUDIO_ITEM | MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_LEFT;
2082 setaudioParams.dwItem = MCI_DGV_SETAUDIO_VOLUME;
2083 sscanf(keywords[i+3], "%lu", &setaudioParams.dwValue);
2084 i += 4;
2085 continue;
2087 FLAG1("off", MCI_SET_OFF);
2088 FLAG1("on", MCI_SET_ON);
2089 if (!STRCMP(keywords[i], "over") && (i+1 < nrofkeywords)) {
2090 dwFlags |= MCI_DGV_SETAUDIO_OVER;
2091 sscanf(keywords[i+3], "%lu", &setaudioParams.dwOver);
2092 i += 2;
2093 continue;
2095 if (!STRCMP(keywords[i], "quality") && (i+1 < nrofkeywords)) {
2096 setaudioParams.lpstrQuality = strdup(keywords[i+1]);
2097 dwFlags |= MCI_DGV_SETAUDIO_QUALITY;
2098 i += 2;
2099 continue;
2101 FLAG2("record", "off", MCI_DGV_SETAUDIO_RECORD|MCI_SET_OFF);
2102 FLAG2("record", "on", MCI_DGV_SETAUDIO_RECORD|MCI_SET_ON);
2103 FLAG2("right", "off", MCI_DGV_SETAUDIO_RIGHT|MCI_SET_OFF);
2104 FLAG2("right", "on", MCI_DGV_SETAUDIO_RIGHT|MCI_SET_ON);
2105 if (!STRCMP(keywords[i], "right") && (i+3 < nrofkeywords) &&
2106 !STRCMP(keywords[i+1], "volume") && !STRCMP(keywords[i+2], "to")) {
2107 dwFlags |= MCI_DGV_SETAUDIO_ITEM | MCI_DGV_SETAUDIO_VALUE | MCI_DGV_SETAUDIO_RIGHT;
2108 setaudioParams.dwItem = MCI_DGV_SETAUDIO_VOLUME;
2109 sscanf(keywords[i+3], "%lu", &setaudioParams.dwValue);
2110 i += 4;
2111 continue;
2113 if (!STRCMP(keywords[i], "source") && (i+2 < nrofkeywords) && !STRCMP(keywords[i+1], "to")) {
2114 dwFlags |= MCI_DGV_SETAUDIO_ITEM;
2115 setaudioParams.dwItem |= MCI_DGV_SETAUDIO_SOURCE;
2116 if (!STRCMP(keywords[i+2], "left")) {
2117 setaudioParams.dwValue |= MCI_DGV_SETAUDIO_SOURCE_LEFT;
2118 } else if (!STRCMP(keywords[i+2], "right")) {
2119 setaudioParams.dwValue |= MCI_DGV_SETAUDIO_SOURCE_RIGHT;
2120 } else if (!STRCMP(keywords[i+2], "average")) {
2121 setaudioParams.dwValue |= MCI_DGV_SETAUDIO_SOURCE_AVERAGE;
2122 } else if (!STRCMP(keywords[i+2], "stereo")) {
2123 setaudioParams.dwValue |= MCI_DGV_SETAUDIO_SOURCE_STEREO;
2124 } else {
2125 res = MCIERR_UNSUPPORTED_FUNCTION;
2126 return res;
2128 i += 3;
2129 continue;
2132 res = mciSendCommandA(wDevID, MCI_SETAUDIO, dwFlags, (DWORD)&setaudioParams);
2133 free(setaudioParams.lpstrAlgorithm);
2134 free(setaudioParams.lpstrQuality);
2135 return res;
2138 /* videodisc spinning
2139 * "up"
2140 * "down"
2142 static DWORD
2143 MCISTR_Spin(_MCISTR_PROTO_)
2145 MCI_GENERIC_PARMS *spinParams = xmalloc(sizeof(MCI_GENERIC_PARMS));
2146 int i, res;
2148 if (uDevTyp != MCI_DEVTYPE_VIDEODISC)
2149 return MCIERR_UNSUPPORTED_FUNCTION;
2150 for (i = 0; i < nrofkeywords; i++) {
2151 FLAG1("up", MCI_VD_SPIN_UP);
2152 FLAG1("down", MCI_VD_SPIN_UP);
2154 spinParams->dwCallback = hwndCallback;
2155 res = mciSendCommandA(wDevID, MCI_SPIN, dwFlags, (DWORD)spinParams);
2156 free(spinParams);
2157 return res;
2160 /* step single frames
2161 * "reverse" optional flag
2162 * "by <nr>" for <nr> frames
2164 static DWORD
2165 MCISTR_Step(_MCISTR_PROTO_) {
2166 union U {
2167 MCI_ANIM_STEP_PARMS animstepParams;
2168 MCI_VD_STEP_PARMS vdstepParams;
2170 union U *pU = xmalloc(sizeof(union U));
2171 int i, res;
2173 for (i = 0; i < nrofkeywords; ) {
2174 switch (uDevTyp) {
2175 case MCI_DEVTYPE_ANIMATION:
2176 FLAG1("reverse", MCI_ANIM_STEP_REVERSE);
2177 if (!STRCMP(keywords[i], "by") && (i+1 < nrofkeywords)) {
2178 sscanf(keywords[i+1], "%ld", &(pU->animstepParams.dwFrames));
2179 dwFlags |= MCI_ANIM_STEP_FRAMES;
2180 i += 2;
2181 continue;
2183 break;
2184 case MCI_DEVTYPE_VIDEODISC:
2185 FLAG1("reverse", MCI_VD_STEP_REVERSE);
2186 if (!STRCMP(keywords[i], "by") && (i+1 < nrofkeywords)) {
2187 sscanf(keywords[i+1], "%ld", &(pU->vdstepParams.dwFrames));
2188 dwFlags |= MCI_VD_STEP_FRAMES;
2189 i += 2;
2190 continue;
2192 break;
2194 i++;
2196 pU->animstepParams.dwCallback = hwndCallback;
2197 res = mciSendCommandA(wDevID, MCI_STEP, dwFlags, (DWORD)pU);
2198 free(pU);
2199 return res;
2202 /* update animation window
2203 * Arguments:
2204 * "at <left> <top> <right> <bottom>" only in this rectangle
2205 * "hdc" device context
2207 static DWORD
2208 MCISTR_Update(_MCISTR_PROTO_) {
2209 int i, res;
2210 LPMCI_ANIM_UPDATE_PARMS updateParams = xmalloc(sizeof(MCI_ANIM_UPDATE_PARMS));
2212 for (i = 0; i < nrofkeywords; ) {
2213 if (!STRCMP(keywords[i], "at") && (i+4 < nrofkeywords)) {
2214 sscanf(keywords[i+1], "%d", &(updateParams->rc.left));
2215 sscanf(keywords[i+2], "%d", &(updateParams->rc.top));
2216 sscanf(keywords[i+3], "%d", &(updateParams->rc.right));
2217 sscanf(keywords[i+4], "%d", &(updateParams->rc.bottom));
2218 dwFlags |= MCI_ANIM_RECT;
2219 i += 5;
2220 continue;
2222 if (!STRCMP(keywords[i], "hdc") && (i+1 < nrofkeywords)) {
2223 dwFlags |= MCI_ANIM_UPDATE_HDC;
2224 sscanf(keywords[i+1], "%d", &(updateParams->hDC));
2225 i += 2;
2226 continue;
2228 i++;
2230 updateParams->dwCallback = hwndCallback;
2231 res = mciSendCommandA(wDevID, MCI_UPDATE, dwFlags, (DWORD)updateParams);
2232 free(updateParams);
2233 return res;
2236 /* where command for animation and overlay drivers.
2237 * just returns the specified rectangle as a string
2238 * Arguments:
2239 * "source"
2240 * "destination"
2241 * Overlay special:
2242 * "video"
2243 * "frame"
2245 static DWORD
2246 MCISTR_Where(_MCISTR_PROTO_) {
2247 union U {
2248 MCI_ANIM_RECT_PARMS animwhereParams;
2249 MCI_OVLY_RECT_PARMS ovlywhereParams;
2251 union U* pU = xmalloc(sizeof(union U));
2252 int i, res;
2254 for (i = 0; i < nrofkeywords; i++) {
2255 switch (uDevTyp) {
2256 case MCI_DEVTYPE_ANIMATION:
2257 FLAG1("source", MCI_ANIM_WHERE_SOURCE);
2258 FLAG1("destination", MCI_ANIM_WHERE_DESTINATION);
2259 break;
2260 case MCI_DEVTYPE_OVERLAY:
2261 FLAG1("source", MCI_OVLY_WHERE_SOURCE);
2262 FLAG1("destination", MCI_OVLY_WHERE_DESTINATION);
2263 FLAG1("video", MCI_OVLY_WHERE_VIDEO);
2264 FLAG1("frame", MCI_OVLY_WHERE_FRAME);
2265 break;
2268 pU->animwhereParams.dwCallback = hwndCallback;
2269 res = mciSendCommandA(wDevID, MCI_WHERE, dwFlags, (DWORD)pU);
2270 if (res == 0) {
2271 char buf[100];
2272 switch (uDevTyp) {
2273 case MCI_DEVTYPE_ANIMATION:
2274 sprintf(buf, "%d %d %d %d",
2275 pU->animwhereParams.rc.left,
2276 pU->animwhereParams.rc.top,
2277 pU->animwhereParams.rc.right,
2278 pU->animwhereParams.rc.bottom
2280 break;
2281 case MCI_DEVTYPE_OVERLAY:
2282 sprintf(buf, "%d %d %d %d",
2283 pU->ovlywhereParams.rc.left,
2284 pU->ovlywhereParams.rc.top,
2285 pU->ovlywhereParams.rc.right,
2286 pU->ovlywhereParams.rc.bottom
2288 break;
2289 default:strcpy(buf, "0 0 0 0");break;
2291 _MCI_STR(buf);
2293 free(pU);
2294 return res;
2297 static DWORD
2298 MCISTR_Window(_MCISTR_PROTO_) {
2299 union U {
2300 MCI_ANIM_WINDOW_PARMSA animwindowParams;
2301 MCI_OVLY_WINDOW_PARMSA ovlywindowParams;
2302 MCI_DGV_WINDOW_PARMSA dgvwindowParams;
2304 union U* pU = xmalloc(sizeof(union U));
2305 int i, res;
2306 char* s;
2308 s = NULL;
2309 for (i = 0; i < nrofkeywords; ) {
2310 switch (uDevTyp) {
2311 case MCI_DEVTYPE_ANIMATION:
2312 if (!STRCMP(keywords[i], "handle") && (i+1 < nrofkeywords)) {
2313 dwFlags |= MCI_ANIM_WINDOW_HWND;
2314 if (!STRCMP(keywords[i+1], "default"))
2315 pU->animwindowParams.hWnd = MCI_OVLY_WINDOW_DEFAULT;
2316 else
2317 sscanf(keywords[i+1], "%d", &(pU->animwindowParams.hWnd));
2318 i += 2;
2319 continue;
2321 if (!STRCMP(keywords[i], "state") && (i+1 < nrofkeywords)) {
2322 dwFlags |= MCI_ANIM_WINDOW_STATE;
2323 if (!STRCMP(keywords[i+1], "hide"))
2324 pU->animwindowParams.nCmdShow = SW_HIDE;
2325 if (!STRCMP(keywords[i+1], "iconic"))
2326 pU->animwindowParams.nCmdShow = SW_SHOWMINNOACTIVE; /* correct? */
2327 if (!STRCMP(keywords[i+1], "minimized"))
2328 pU->animwindowParams.nCmdShow = SW_SHOWMINIMIZED;
2329 if (!STRCMP(keywords[i+1], "maximized"))
2330 pU->animwindowParams.nCmdShow = SW_SHOWMAXIMIZED;
2331 if (!STRCMP(keywords[i+1], "minimize"))
2332 pU->animwindowParams.nCmdShow = SW_MINIMIZE;
2333 if (!STRCMP(keywords[i+1], "normal"))
2334 pU->animwindowParams.nCmdShow = SW_NORMAL;
2335 if (!STRCMP(keywords[i+1], "restore"))
2336 pU->animwindowParams.nCmdShow = SW_NORMAL;
2337 if (!STRCMP(keywords[i+1], "show"))
2338 pU->animwindowParams.nCmdShow = SW_SHOW;
2339 if (!STRCMP(keywords[i+1], "no") && (i+2 < nrofkeywords)) {
2340 if (!STRCMP(keywords[i+2], "active"))
2341 pU->animwindowParams.nCmdShow = SW_SHOWNOACTIVATE;
2342 if (!STRCMP(keywords[i+2], "action"))
2343 pU->animwindowParams.nCmdShow = SW_SHOWNA;/* correct?*/
2344 i++;
2346 i += 2;
2347 continue;
2349 /* text is enclosed in " ... " as it seems */
2350 if (!STRCMP(keywords[i], "text")) {
2351 char *t;
2352 int len, j, k;
2354 if (keywords[i+1][0] != '"') {
2355 i++;
2356 continue;
2358 dwFlags |= MCI_ANIM_WINDOW_TEXT;
2359 len = strlen(keywords[i+1])+1;
2360 for (j = i+2; j < nrofkeywords; j++) {
2361 len += strlen(keywords[j])+1;
2362 if (strchr(keywords[j], '"'))
2363 break;
2365 s = (char*)xmalloc(len);
2366 strcpy(s, keywords[i+1]+1);
2367 k = j;
2368 for (j = i + 2; j <= k; j++) {
2369 strcat(s, " ");
2370 strcat(s, keywords[j]);
2372 /* FIXME: hhmmm not so sure (strrchr ?) */
2373 if ((t=strchr(s, '"'))) *t='\0';
2374 pU->animwindowParams.lpstrText = s;
2375 i = k+1;
2376 continue;
2378 FLAG1("stretch", MCI_ANIM_WINDOW_ENABLE_STRETCH);
2379 break;
2380 case MCI_DEVTYPE_DIGITAL_VIDEO:
2381 if (!STRCMP(keywords[i], "handle") && (i+1 < nrofkeywords)) {
2382 dwFlags |= MCI_DGV_WINDOW_HWND;
2383 if (!STRCMP(keywords[i+1], "default"))
2384 pU->dgvwindowParams.hWnd = MCI_OVLY_WINDOW_DEFAULT;
2385 else
2386 sscanf(keywords[i+1], "%d", &(pU->dgvwindowParams.hWnd));
2387 i += 2;
2388 continue;
2390 if (!STRCMP(keywords[i], "state") && (i+1 < nrofkeywords)) {
2391 dwFlags |= MCI_DGV_WINDOW_STATE;
2392 if (!STRCMP(keywords[i+1], "hide"))
2393 pU->dgvwindowParams.nCmdShow = SW_HIDE;
2394 if (!STRCMP(keywords[i+1], "iconic"))
2395 pU->dgvwindowParams.nCmdShow = SW_SHOWMINNOACTIVE; /* correct? */
2396 if (!STRCMP(keywords[i+1], "minimized"))
2397 pU->dgvwindowParams.nCmdShow = SW_SHOWMINIMIZED;
2398 if (!STRCMP(keywords[i+1], "maximized"))
2399 pU->dgvwindowParams.nCmdShow = SW_SHOWMAXIMIZED;
2400 if (!STRCMP(keywords[i+1], "minimize"))
2401 pU->dgvwindowParams.nCmdShow = SW_MINIMIZE;
2402 if (!STRCMP(keywords[i+1], "normal"))
2403 pU->dgvwindowParams.nCmdShow = SW_NORMAL;
2404 if (!STRCMP(keywords[i+1], "restore"))
2405 pU->dgvwindowParams.nCmdShow = SW_NORMAL;
2406 if (!STRCMP(keywords[i+1], "show"))
2407 pU->dgvwindowParams.nCmdShow = SW_SHOW;
2408 if (!STRCMP(keywords[i+1], "no") && (i+2 < nrofkeywords)) {
2409 if (!STRCMP(keywords[i+2], "active"))
2410 pU->dgvwindowParams.nCmdShow = SW_SHOWNOACTIVATE;
2411 if (!STRCMP(keywords[i+2], "action"))
2412 pU->dgvwindowParams.nCmdShow = SW_SHOWNA;/* correct?*/
2413 i++;
2415 i += 2;
2416 continue;
2418 /* text is enclosed in " ... " as it seems */
2419 if (!STRCMP(keywords[i], "text")) {
2420 char *t;
2421 int len, j, k;
2423 if (keywords[i+1][0] != '"') {
2424 i++;
2425 continue;
2427 dwFlags |= MCI_DGV_WINDOW_TEXT;
2428 len = strlen(keywords[i+1])+1;
2429 for (j = i+2; j < nrofkeywords; j++) {
2430 len += strlen(keywords[j])+1;
2431 if (strchr(keywords[j], '"'))
2432 break;
2434 s = (char*)xmalloc(len);
2435 strcpy(s, keywords[i+1]+1);
2436 k = j;
2437 for (j = i + 2; j <= k; j++) {
2438 strcat(s, " ");
2439 strcat(s, keywords[j]);
2441 /* FIXME: hhmmm not so sure (strrchr ?) */
2442 if ((t=strchr(s, '"'))) *t='\0';
2443 pU->dgvwindowParams.lpstrText = s;
2444 i = k+1;
2445 continue;
2447 break;
2449 case MCI_DEVTYPE_OVERLAY:
2450 if (!STRCMP(keywords[i], "handle") && (i+1 < nrofkeywords)) {
2451 dwFlags |= MCI_OVLY_WINDOW_HWND;
2452 if (!STRCMP(keywords[i+1], "default"))
2453 pU->ovlywindowParams.hWnd = MCI_OVLY_WINDOW_DEFAULT;
2454 else
2455 sscanf(keywords[i+1], "%d", &(pU->ovlywindowParams.hWnd));
2456 i += 2;
2457 continue;
2459 if (!STRCMP(keywords[i], "state") && (i+1 < nrofkeywords)) {
2460 dwFlags |= MCI_OVLY_WINDOW_STATE;
2461 if (!STRCMP(keywords[i+1], "hide"))
2462 pU->ovlywindowParams.nCmdShow = SW_HIDE;
2463 if (!STRCMP(keywords[i+1], "iconic"))
2464 pU->ovlywindowParams.nCmdShow = SW_SHOWMINNOACTIVE; /* correct? */
2465 if (!STRCMP(keywords[i+1], "minimized"))
2466 pU->ovlywindowParams.nCmdShow = SW_SHOWMINIMIZED;
2467 if (!STRCMP(keywords[i+1], "maximized"))
2468 pU->ovlywindowParams.nCmdShow = SW_SHOWMAXIMIZED;
2469 if (!STRCMP(keywords[i+1], "minimize"))
2470 pU->ovlywindowParams.nCmdShow = SW_MINIMIZE;
2471 if (!STRCMP(keywords[i+1], "normal"))
2472 pU->ovlywindowParams.nCmdShow = SW_NORMAL;
2473 if (!STRCMP(keywords[i+1], "show"))
2474 pU->ovlywindowParams.nCmdShow = SW_SHOW;
2475 if (!STRCMP(keywords[i+1], "no") && (i+2 < nrofkeywords)) {
2476 if (!STRCMP(keywords[i+2], "active"))
2477 pU->ovlywindowParams.nCmdShow = SW_SHOWNOACTIVATE;
2478 if (!STRCMP(keywords[i+2], "action"))
2479 pU->ovlywindowParams.nCmdShow = SW_SHOWNA;/* correct?*/
2480 i++;
2482 i += 2;
2483 continue;
2485 /* text is enclosed in " ... " as it seems */
2486 if (!STRCMP(keywords[i], "text")) {
2487 char *t;
2488 int len, j, k;
2490 if (keywords[i+1][0] != '"') {
2491 i++;
2492 continue;
2494 dwFlags |= MCI_OVLY_WINDOW_TEXT;
2495 len = strlen(keywords[i+1])+1;
2496 for (j = i+2; j < nrofkeywords; j++) {
2497 len += strlen(keywords[j])+1;
2498 if (strchr(keywords[j], '"'))
2499 break;
2501 s=(char*)xmalloc(len);
2502 strcpy(s, keywords[i+1]+1);
2503 k = j;
2504 for (j = i+2; j <= k; j++) {
2505 strcat(s, " ");
2506 strcat(s, keywords[j]);
2508 if ((t=strchr(s, '"'))) *t='\0';
2509 pU->ovlywindowParams.lpstrText = s;
2510 i = k+1;
2511 continue;
2513 FLAG1("stretch", MCI_OVLY_WINDOW_ENABLE_STRETCH);
2514 break;
2516 i++;
2518 pU->animwindowParams.dwCallback = hwndCallback;
2519 res = mciSendCommandA(wDevID, MCI_WINDOW, dwFlags, (DWORD)pU);
2520 if (s) free(s);
2521 free(pU);
2522 return res;
2525 struct _MCISTR_cmdtable {
2526 char *cmd;
2527 DWORD (*fun)(_MCISTR_PROTO_);
2528 } MCISTR_cmdtable[]={
2529 {"break", MCISTR_Break},
2530 {"capability", MCISTR_Capability},
2531 {"close", MCISTR_Close},
2532 {"cue", MCISTR_Cue},
2533 {"delete", MCISTR_Delete},
2534 {"escape", MCISTR_Escape},
2535 {"freeze", MCISTR_Freeze},
2536 {"info", MCISTR_Info},
2537 {"load", MCISTR_Load},
2538 {"open", MCISTR_Open},
2539 {"pause", MCISTR_Pause},
2540 {"play", MCISTR_Play},
2541 {"put", MCISTR_Put},
2542 {"realize", MCISTR_Realize},
2543 {"record", MCISTR_Record},
2544 {"resume", MCISTR_Resume},
2545 {"save", MCISTR_Save},
2546 {"seek", MCISTR_Seek},
2547 {"set", MCISTR_Set},
2548 {"setaudio", MCISTR_SetAudio},
2549 {"spin", MCISTR_Spin},
2550 {"status", MCISTR_Status},
2551 {"step", MCISTR_Step},
2552 {"stop", MCISTR_Stop},
2553 {"sysinfo", MCISTR_Sysinfo},
2554 {"unfreeze", MCISTR_Unfreeze},
2555 {"update", MCISTR_Update},
2556 {"where", MCISTR_Where},
2557 {"window", MCISTR_Window},
2558 {NULL, NULL}
2561 /**************************************************************************
2562 * mciSendString16 [MMSYSTEM.702]
2564 /* The usercode sends a string with a command (and flags) expressed in
2565 * words in it... We do our best to call appropriate drivers,
2566 * and return a errorcode AND a readable string (if lpstrRS != NULL)
2567 * Info gathered by watching cool134.exe and from Borland's mcistrwh.hlp
2569 /* FIXME: "all" is a valid devicetype and we should access all devices if
2570 * it is used. (imagine "close all"). Not implemented yet.
2572 DWORD WINAPI mciSendString16(LPCSTR lpstrCommand, LPSTR lpstrReturnString,
2573 UINT16 uReturnLength, HWND16 hwndCallback)
2575 char *cmd, *dev, *args, **keywords;
2576 WORD uDevTyp = 0, wDevID = 0;
2577 DWORD dwFlags;
2578 int res = 0, i, nrofkeywords;
2580 TRACE(mci, "('%s', %p, %d, %X)\n",
2581 lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback);
2583 /* format is <command> <device> <optargs> */
2584 cmd = strdup(lpstrCommand);
2585 dev = strchr(cmd, ' ');
2586 if (dev == NULL) {
2587 free(cmd);
2588 return MCIERR_MISSING_DEVICE_NAME;
2590 *dev++ = '\0';
2591 args = strchr(dev, ' ');
2592 if (args != NULL) *args++ = '\0';
2594 if (args != NULL) {
2595 char *s;
2596 i = 1;/* nrofkeywords = nrofspaces+1 */
2597 s = args;
2598 while ((s = strchr(s, ' ')) != NULL) i++, s++;
2599 keywords = (char**)xmalloc(sizeof(char*) * (i + 2));
2600 nrofkeywords = i;
2601 s = args; i = 0;
2602 while (s && i < nrofkeywords) {
2603 keywords[i++] = s;
2604 s = strchr(s, ' ');
2605 if (s) *s++ = '\0';
2607 keywords[i] = NULL;
2608 } else {
2609 nrofkeywords = 0;
2610 keywords = (char**)xmalloc(sizeof(char*));
2612 dwFlags = 0; /* default flags */
2613 for (i = 0; i < nrofkeywords;) {
2614 if (!STRCMP(keywords[i], "wait")) {
2615 dwFlags |= MCI_WAIT;
2616 memcpy(keywords+i, keywords+(i+1), (nrofkeywords-i-1) * sizeof(char*));
2617 nrofkeywords--;
2618 continue;
2620 if (!STRCMP(keywords[i], "notify")) {
2621 dwFlags |= MCI_NOTIFY;
2622 memcpy(keywords+i, keywords+(i+1), (nrofkeywords-i-1) * sizeof(char*));
2623 nrofkeywords--;
2624 continue;
2626 i++;
2629 /* determine wDevID and uDevTyp for all commands except "open" */
2630 if (STRCMP(cmd, "open") != 0) {
2631 wDevID = mciGetDeviceIDA(dev);
2632 if (wDevID == 0) {
2633 TRACE(mci, "Device '%s' not found!\n", dev);
2634 res = MCIERR_INVALID_DEVICE_NAME;
2635 goto the_end;
2637 uDevTyp = MCI_GetDrv(wDevID)->modp.wType;
2640 for (i = 0; MCISTR_cmdtable[i].cmd != NULL; i++) {
2641 if (!STRCMP(MCISTR_cmdtable[i].cmd, cmd)) {
2642 res = MCISTR_cmdtable[i].fun(wDevID, uDevTyp, lpstrReturnString,
2643 uReturnLength, dev, (LPSTR*)keywords,
2644 nrofkeywords, dwFlags, hwndCallback);
2645 break;
2648 if (MCISTR_cmdtable[i].cmd == NULL) {
2649 FIXME(mci, "('%s', %p, %u, %X): unimplemented, please report.\n",
2650 lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback);
2651 res = MCIERR_MISSING_COMMAND_STRING;
2653 the_end:
2654 free(keywords); free(cmd);
2655 return res;
2658 /**************************************************************************
2659 * mciSendStringA [MMSYSTEM.702][WINMM.51]
2661 DWORD WINAPI mciSendStringA(LPCSTR lpstrCommand, LPSTR lpstrReturnString,
2662 UINT uReturnLength, HWND hwndCallback)
2664 return mciSendString16(lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback);
2667 /**************************************************************************
2668 * mciSendStringW [WINMM.52]
2670 DWORD WINAPI mciSendStringW(LPCWSTR lpwstrCommand, LPSTR lpstrReturnString,
2671 UINT uReturnLength, HWND hwndCallback)
2673 LPSTR lpstrCommand;
2674 UINT ret;
2676 /* FIXME: is there something to do with lpstrReturnString ? */
2677 lpstrCommand = HEAP_strdupWtoA(GetProcessHeap(), 0, lpwstrCommand);
2678 ret = mciSendString16(lpstrCommand, lpstrReturnString, uReturnLength, hwndCallback);
2679 HeapFree(GetProcessHeap(), 0, lpstrCommand);
2680 return ret;
2683 /**************************************************************************
2684 * mciExecute [WINMM.38]
2686 DWORD WINAPI mciExecute(LPCSTR lpstrCommand)
2688 char strRet[256];
2689 DWORD ret;
2691 TRACE(mci, "(%s)!\n", lpstrCommand);
2693 ret = mciSendString16(lpstrCommand, strRet, sizeof(strRet), 0);
2694 if (ret != 0) {
2695 if (!mciGetErrorString16(ret, strRet, sizeof(strRet))) {
2696 sprintf(strRet, "Unknown MCI error (%ld)", ret);
2698 MessageBoxA(0, strRet, "Error in mciExecute()", MB_OK);
2700 /* FIXME: what shall I return ? */
2701 return 0;