/* * MCI stringinterface * * Copyright 1995 Marcus Meissner */ /* FIXME: special commands of device drivers should be handled by those drivers */ #ifndef WINELIB #include #include #include #include #include #include #include "windows.h" #include "ldt.h" #include "user.h" #include "driver.h" #include "mmsystem.h" #include "stackframe.h" #include "stddebug.h" #include "debug.h" #include "xmalloc.h" extern MCI_OPEN_DRIVER_PARMS mciDrv[MAXMCIDRIVERS]; /* FIXME: I need to remember the aliasname of a spec. driver. * and this is the easiest way. *sigh* */ extern MCI_OPEN_PARMS mciOpenDrv[MAXMCIDRIVERS]; LONG DrvDefDriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, DWORD dwParam1, DWORD dwParam2); LONG WAVE_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, DWORD dwParam1, DWORD dwParam2); LONG MIDI_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, DWORD dwParam1, DWORD dwParam2); LONG CDAUDIO_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, DWORD dwParam1, DWORD dwParam2); LONG ANIM_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, DWORD dwParam1, DWORD dwParam2); /* The reason why I just don't lowercase the keywords array in * mciSendString is left as an exercise to the reader. */ #define STRCMP(x,y) lstrcmpi32A(x,y) /* standard functionparameters for all functions */ #define _MCISTR_PROTO_ \ WORD wDevID,WORD uDevTyp,LPSTR lpstrReturnString,UINT uReturnLength,\ LPCSTR dev,LPSTR *keywords,UINT nrofkeywords,DWORD dwFlags /* copy string to return pointer including necessary checks * for use in mciSendString() */ #define _MCI_STR(s) do {\ dprintf_mci(stddeb,"->returns \"%s\"",s);\ if (lpstrReturnString) {\ lstrcpyn32A(lpstrReturnString,s,uReturnLength);\ dprintf_mci(stddeb,"-->\"%s\"\n",lpstrReturnString);\ }\ } while(0) /* calling DriverProc. We need to pass the struct as SEGMENTED POINTER. */ #define _MCI_CALL_DRIVER(cmd,params) \ switch(uDevTyp) {\ case MCI_DEVTYPE_CD_AUDIO:\ res=CDAUDIO_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags, (DWORD)(params));\ break;\ case MCI_DEVTYPE_WAVEFORM_AUDIO:\ res=WAVE_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,(DWORD)(params));\ break;\ case MCI_DEVTYPE_SEQUENCER:\ res=MIDI_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,(DWORD)(params));\ break;\ case MCI_DEVTYPE_ANIMATION:\ res=ANIM_DriverProc(mciDrv[wDevID].wDeviceID,0,cmd,dwFlags,(DWORD)(params));\ break;\ case MCI_DEVTYPE_DIGITAL_VIDEO:\ dprintf_mci(stddeb,"_MCI_CALL_DRIVER //No DIGITAL_VIDEO yet !\n");\ res=MCIERR_DEVICE_NOT_INSTALLED;\ break;\ default:\ dprintf_mci(stddeb,"_MCI_CALL_DRIVER //Invalid Device Name '%s' !\n",dev);\ res=MCIERR_INVALID_DEVICE_NAME;\ break;\ } /* we need to have strings in 16 bit space for some things * FIXME: this is bad. */ #define _MCI_STRDUP_TO_SEG(dest,source) {\ HANDLE x;\ x=USER_HEAP_ALLOC(strlen(source));\ dest=(LPSTR)MAKELONG(x,USER_HeapSel);\ strcpy(PTR_SEG_TO_LIN(dest),source);\ } /* print a DWORD in the specified timeformat */ static void _MCISTR_printtf(char *buf,UINT uDevType,DWORD timef,DWORD val) { *buf='\0'; switch (timef) { case MCI_FORMAT_MILLISECONDS: case MCI_FORMAT_FRAMES: case MCI_FORMAT_BYTES: case MCI_FORMAT_SAMPLES: case MCI_VD_FORMAT_TRACK: /*case MCI_SEQ_FORMAT_SONGPTR: sameas MCI_VD_FORMAT_TRACK */ sprintf(buf,"%ld",val); break; case MCI_FORMAT_HMS: /* well, the macros have the same content*/ /*FALLTRHOUGH*/ case MCI_FORMAT_MSF: sprintf(buf,"%d:%d:%d", MCI_HMS_HOUR(val), MCI_HMS_MINUTE(val), MCI_HMS_SECOND(val) ); break; case MCI_FORMAT_TMSF: sprintf(buf,"%d:%d:%d:%d", MCI_TMSF_TRACK(val), MCI_TMSF_MINUTE(val), MCI_TMSF_SECOND(val), MCI_TMSF_FRAME(val) ); break; default: fprintf(stdnimp,__FILE__":MCISTR_Status:missing timeformat for %ld, report.\n",timef); strcpy(buf,"0"); /* hmm */ break; } return; } /* possible different return types */ #define _MCISTR_int 1 #define _MCISTR_time 2 #define _MCISTR_bool 3 #define _MCISTR_tfname 4 #define _MCISTR_mode 5 #define _MCISTR_divtype 6 #define _MCISTR_seqtype 7 #define _MCISTR_vdmtype 8 #define _MCISTR_devtype 9 static void _MCISTR_convreturn(int type,DWORD dwReturn,LPSTR lpstrReturnString, WORD uReturnLength,WORD uDevTyp,int timef ) { switch (type) { case _MCISTR_vdmtype: switch (dwReturn) { case MCI_VD_MEDIA_CLV:_MCI_STR("CLV");break; case MCI_VD_MEDIA_CAV:_MCI_STR("CAV");break; default: case MCI_VD_MEDIA_OTHER:_MCI_STR("other");break; } break; case _MCISTR_seqtype: switch (dwReturn) { case MCI_SEQ_NONE:_MCI_STR("none");break; case MCI_SEQ_SMPTE:_MCI_STR("smpte");break; case MCI_SEQ_FILE:_MCI_STR("file");break; case MCI_SEQ_MIDI:_MCI_STR("midi");break; default:fprintf(stdnimp,__FILE__":MCISTR_Status:missing sequencer mode %ld\n",dwReturn); } break; case _MCISTR_mode: switch (dwReturn) { case MCI_MODE_NOT_READY:_MCI_STR("not ready");break; case MCI_MODE_STOP:_MCI_STR("stopped");break; case MCI_MODE_PLAY:_MCI_STR("playing");break; case MCI_MODE_RECORD:_MCI_STR("recording");break; case MCI_MODE_SEEK:_MCI_STR("seeking");break; case MCI_MODE_PAUSE:_MCI_STR("paused");break; case MCI_MODE_OPEN:_MCI_STR("open");break; default:break; } break; case _MCISTR_bool: if (dwReturn) _MCI_STR("true"); else _MCI_STR("false"); break; case _MCISTR_int:{ char buf[16]; sprintf(buf,"%ld",dwReturn); _MCI_STR(buf); break; } case _MCISTR_time: { char buf[100]; _MCISTR_printtf(buf,uDevTyp,timef,dwReturn); _MCI_STR(buf); break; } case _MCISTR_tfname: switch (timef) { case MCI_FORMAT_MILLISECONDS:_MCI_STR("milliseconds");break; case MCI_FORMAT_FRAMES:_MCI_STR("frames");break; case MCI_FORMAT_BYTES:_MCI_STR("bytes");break; case MCI_FORMAT_SAMPLES:_MCI_STR("samples");break; case MCI_FORMAT_HMS:_MCI_STR("hms");break; case MCI_FORMAT_MSF:_MCI_STR("msf");break; case MCI_FORMAT_TMSF:_MCI_STR("tmsf");break; default: fprintf(stdnimp,__FILE__":MCISTR_Status:missing timeformat for %d, report.\n",timef); break; } break; case _MCISTR_divtype: switch (dwReturn) { case MCI_SEQ_DIV_PPQN:_MCI_STR("PPQN");break; case MCI_SEQ_DIV_SMPTE_24:_MCI_STR("SMPTE 24 frame");break; case MCI_SEQ_DIV_SMPTE_25:_MCI_STR("SMPTE 25 frame");break; case MCI_SEQ_DIV_SMPTE_30:_MCI_STR("SMPTE 30 frame");break; case MCI_SEQ_DIV_SMPTE_30DROP:_MCI_STR("SMPTE 30 frame drop");break; } case _MCISTR_devtype: switch (dwReturn) { case MCI_DEVTYPE_VCR:_MCI_STR("vcr");break; case MCI_DEVTYPE_VIDEODISC:_MCI_STR("videodisc");break; case MCI_DEVTYPE_CD_AUDIO:_MCI_STR("cd audio");break; case MCI_DEVTYPE_OVERLAY:_MCI_STR("overlay");break; case MCI_DEVTYPE_DAT:_MCI_STR("dat");break; case MCI_DEVTYPE_SCANNER:_MCI_STR("scanner");break; case MCI_DEVTYPE_ANIMATION:_MCI_STR("animation");break; case MCI_DEVTYPE_DIGITAL_VIDEO:_MCI_STR("digital video");break; case MCI_DEVTYPE_OTHER:_MCI_STR("other");break; case MCI_DEVTYPE_WAVEFORM_AUDIO:_MCI_STR("waveform audio");break; case MCI_DEVTYPE_SEQUENCER:_MCI_STR("sequencer");break; default:fprintf(stdnimp,__FILE__":_MCISTR_convreturn:unknown device type %ld, report.\n",dwReturn);break; } break; default: fprintf(stdnimp,__FILE__":_MCISTR_convreturn:unknown resulttype %d, report.\n",type); break; } } #define FLAG1(str,flag) \ if (!STRCMP(keywords[i],str)) {\ dwFlags |= flag;\ i++;\ continue;\ } #define FLAG2(str1,str2,flag) \ if (!STRCMP(keywords[i],str1) && (i+1 * Optional: * "shareable" * "alias " * "element " * Additional: * waveform audio: * "buffer " * Animation: * "nostatic" increaste nr of nonstatic colours * "parent " * "style " bitmask of WS_xxxxx (see windows.h) * "style child" WS_CHILD * "style overlap" WS_OVERLAPPED * "style popup" WS_POPUP * Overlay: * "parent " * "style " bitmask of WS_xxxxx (see windows.h) * "style child" WS_CHILD * "style overlap" WS_OVERLAPPED * "style popup" WS_POPUP * Returns nothing. */ static DWORD MCISTR_Open(_MCISTR_PROTO_) { int res,i; char *s; union { MCI_OPEN_PARMS openParams; MCI_WAVE_OPEN_PARMS waveopenParams; MCI_ANIM_OPEN_PARMS animopenParams; MCI_OVLY_OPEN_PARMS ovlyopenParams; } U; U.openParams.lpstrElementName = NULL; s=strchr(dev,'!'); if (s!=NULL) { *s++='\0'; _MCI_STRDUP_TO_SEG(U.openParams.lpstrElementName,s); } if (!STRCMP(dev,"cdaudio")) { uDevTyp=MCI_DEVTYPE_CD_AUDIO; } else if (!STRCMP(dev,"waveaudio")) { uDevTyp=MCI_DEVTYPE_WAVEFORM_AUDIO; } else if (!STRCMP(dev,"sequencer")) { uDevTyp=MCI_DEVTYPE_SEQUENCER; } else if (!STRCMP(dev,"animation1")) { uDevTyp=MCI_DEVTYPE_ANIMATION; } else if (!STRCMP(dev,"avivideo")) { uDevTyp=MCI_DEVTYPE_DIGITAL_VIDEO; } else { return MCIERR_INVALID_DEVICE_NAME; } wDevID=0; while(mciDrv[wDevID].wType) { if (++wDevID>=MAXMCIDRIVERS) { dprintf_mci(stddeb, __FILE__":MCISTR_Open:MAXMCIDRIVERS reached!\n"); return MCIERR_INTERNAL; } } mciDrv[wDevID].wType = uDevTyp; mciDrv[wDevID].wDeviceID = wDevID; U.openParams.dwCallback = 0; U.openParams.wDeviceID = wDevID; U.ovlyopenParams.dwStyle = 0; U.animopenParams.dwStyle = 0; _MCI_STRDUP_TO_SEG(U.openParams.lpstrDeviceType,dev); U.openParams.lpstrAlias = NULL; dwFlags |= MCI_OPEN_TYPE; i=0; while (i]" - returns length [of track ] in current * timeformat * "number of tracks" - returns number of tracks as integer * "position [track ]" - returns position [in track ] in current * timeformat * "ready" - checks if device is ready to play, -> bool * "start position" - returns start position in timeformat * "time format" - returns timeformat (list of possible values: * "ms" "msf" "milliseconds" "hmsf" "tmsf" "frames" * "bytes" "samples" "hms") * "media present" - returns if media is present as bool * Animation: * "forward" - returns "true" if device is playing forwards * "speed" - returns speed for device * "palette handle" - returns palette handle * "window handle" - returns window handle * "stretch" - returns stretch bool * MIDI sequencer: * "division type" - ? returns "PPQN" "SMPTE 24 frame" * "SMPTE 25 frame" "SMPTE 30 frame" "SMPTE 30 drop frame" * "tempo" - current tempo in (PPQN? speed in frames, SMPTE*? speed in hsmf) * "offset" - offset in dito. * "port" - midi port as integer * "slave" - slave device ("midi","file","none","smpte") * "master" - masterdevice (dito.) * Overlay: * "window handle" - see animation * "stretch" - dito * Video Disc: * "speed" - speed as integer * "forward" - returns bool (when playing forward) * "side" - returns 1 or 2 * "media type" - returns "CAV" "CLV" "other" * "disc size" - returns "8" or "12" * WAVEFORM audio: * "input" - base queries on input set * "output" - base queries on output set * "format tag" - return integer format tag * "channels" - return integer nr of channels * "bytespersec" - return average nr of bytes/sec * "samplespersec" - return nr of samples per sec * "bitspersample" - return bitspersample * "alignment" - return block alignment * "level" - return level? */ #define ITEM1(str,item,xtype) \ if (!STRCMP(keywords[i],str)) {\ statusParams.dwItem = item;\ type = xtype;\ i++;\ continue;\ } #define ITEM2(str1,str2,item,xtype) \ if ( !STRCMP(keywords[i],str1) &&\ (i+1" "ms" "milliseconds" "msf" "hmsf" * "tmsf" "SMPTE 24" "SMPTE 25" "SMPTE 30" * "SMPTE drop 30" * "audio [all|left|right] [on|off]" sets specified audiochannel on or off * "video [on|off]" sets video on/off * Waveform audio: * "formattag pcm" sets format to pcm * "formattag " sets integer formattag value * "any input" accept input from any known source * "any output" output to any known destination * "input " input from source * "output " output to destination * "channels " sets nr of channels * "bytespersec " sets average bytes per second * "samplespersec " sets average samples per second (1 sample can * be 2 bytes!) * "alignment " sets the blockalignment to * "bitspersample " sets the nr of bits per sample * Sequencer: * "master [midi|file|smpte|none]" sets the midi master device * "slave [midi|file|smpte|none]" sets the midi master device * "port mapper" midioutput to portmapper * "port " midioutput to specified port * "tempo " tempo of track (depends on timeformat/divtype) * "offset " start offset? */ static DWORD MCISTR_Set(_MCISTR_PROTO_) { union { MCI_SET_PARMS setParams; MCI_WAVE_SET_PARMS wavesetParams; MCI_SEQ_SET_PARMS seqsetParams; } U; int i,res; U.setParams.dwCallback = 0; i = 0; while (i */ #define WII(str,flag,fmt,element) \ if (!STRCMP(keywords[i],str) && (i+1" enable break on key with keyid * (I strongly suspect, that there is another parameter: * "window " * but I don't see it mentioned in my documentation. * Returns nothing. */ static DWORD MCISTR_Break(_MCISTR_PROTO_) { MCI_BREAK_PARMS breakParams; int res,i; /*breakParams.hwndBreak ? */ i=0;while (ii+1)) { dwFlags&=~MCI_BREAK_OFF; dwFlags|=MCI_BREAK_KEY; sscanf(keywords[i+1],"%d",&(breakParams.nVirtKey)); i+=2; continue; } i++; } _MCI_CALL_DRIVER( MCI_BREAK, MAKE_SEGPTR(&breakParams) ); return res; } #define ITEM1(str,item,xtype) \ if (!STRCMP(keywords[i],str)) {\ gdcParams.dwItem = item;\ type = xtype;\ i++;\ continue;\ } #define ITEM2(str1,str2,item,xtype) \ if ( !STRCMP(keywords[i],str1) &&\ (i+1" record up to