From 6b81b398f5f083c689dc5d3e06d5637390d0b068 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 7 Jul 1994 16:23:58 +0000 Subject: [PATCH] Release 940706 Sun, 3 Jul 1994 20:15:56 +0100 (BST) David Metcalfe * [controls/edit.c] Bug fixes and tidying up. Preliminary tab stop support (doesn't work yet). * [windows/dialog.c] Reversed order of buttons in CheckRadioButtons so that all buttons are now displayed. Tue Jul 5 18:30:24 1994 Alexandre Julliard (julliard@lamisun.epfl.ch) * [include/options.h] [misc/main.c] [windows/win.c] Removed nosaveunders option, replaced by handling the CS_SAVEBITS flag. * [windows/class.c] Modified the fix for negative size in class extra bytes to avoid modifying the caller's data. * [windows/dc.c] Bug fix: system font must be a proportional font. Fixed a bug that caused the default pen to not be selected correctly in a DC. * [windows/graphics.c] Bug fix in GRAPH_DrawArc(). Thanks to Adriano Azevedo for noticing it. * [windows/painting.c] Removed incorrect selecting of default objects in BeginPaint() (no longer needed because of the fix in dc.c). Jul 4, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte) * [misc/mmsystem.c] * [misc/audio.c] Add more code to interface '/dev/dsp'. * New file [misc/mcicda.c] Create an MCI_DEVTYPE_CD_AUDIO driver connected to '/dev/sbpcd'. * New file [misc/mmaux.c] Stubs to make a future driver connected to '/dev/mixer'. * [windows/win.c] Temporary patch to CreateWindowEx() for reseting negative coordinates to 0,0 ; because 'soundrec.exe' give negative values and I need it to work on MMSYSTEM ... :-) * [miscemu/int2f.c] add a stub 'do_int2f_16' (function 0x16) for DMPI server. Mon Jun 20 10:08:40 BST 1994 William Smith (wos@dcs.warwick.ac.uk) * include/comm.h New file -- some definitions that were in comm.c now need to be shared with misc/dos_fs.c * misc/comm.c Some definitions moved into include/comm.h * misc/dos_fs.c (DOS_GetEquipment): Fixed error in equipment -- bitwise or of two values should be used instead of logical or. Also added code to correctly report the number of serial and parallel devices. --- ChangeLog | 68 +++ controls/edit.c | 277 ++++++--- controls/listbox.c | 2 +- include/comm.h | 21 + include/mmsystem.h | 183 +++++- include/options.h | 1 - include/windows.h | 4 +- loader/main.c | 5 +- misc/Imakefile | 2 + misc/audio.c | 1442 +++++++++++++++++++++++++++++++++++++++++++- misc/comm.c | 11 +- misc/dos_fs.c | 33 +- misc/file.c | 4 +- misc/main.c | 14 +- misc/mcicda.c | 859 ++++++++++++++++++++++++++ misc/mmaux.c | 116 ++++ misc/mmsystem.c | 502 ++++++++++----- miscemu/int2f.c | 43 +- windows/class.c | 23 +- windows/dc.c | 4 +- windows/dialog.c | 4 +- windows/graphics.c | 2 + windows/painting.c | 7 - windows/win.c | 18 +- 24 files changed, 3307 insertions(+), 338 deletions(-) create mode 100644 include/comm.h create mode 100644 misc/mcicda.c create mode 100644 misc/mmaux.c diff --git a/ChangeLog b/ChangeLog index 0e61684e88b..adcba41e1ca 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,71 @@ +---------------------------------------------------------------------- +Sun, 3 Jul 1994 20:15:56 +0100 (BST) David Metcalfe + + * [controls/edit.c] + Bug fixes and tidying up. Preliminary tab stop support + (doesn't work yet). + + * [windows/dialog.c] + Reversed order of buttons in CheckRadioButtons so that all + buttons are now displayed. + +Tue Jul 5 18:30:24 1994 Alexandre Julliard (julliard@lamisun.epfl.ch) + + * [include/options.h] [misc/main.c] [windows/win.c] + Removed nosaveunders option, replaced by handling + the CS_SAVEBITS flag. + + * [windows/class.c] + Modified the fix for negative size in class extra bytes to + avoid modifying the caller's data. + + * [windows/dc.c] + Bug fix: system font must be a proportional font. + Fixed a bug that caused the default pen to not be selected + correctly in a DC. + + * [windows/graphics.c] + Bug fix in GRAPH_DrawArc(). Thanks to Adriano Azevedo for + noticing it. + + * [windows/painting.c] + Removed incorrect selecting of default objects in BeginPaint() + (no longer needed because of the fix in dc.c). + +Jul 4, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte) + + * [misc/mmsystem.c] + * [misc/audio.c] + Add more code to interface '/dev/dsp'. + + * New file [misc/mcicda.c] + Create an MCI_DEVTYPE_CD_AUDIO driver connected to '/dev/sbpcd'. + + * New file [misc/mmaux.c] + Stubs to make a future driver connected to '/dev/mixer'. + + * [windows/win.c] + Temporary patch to CreateWindowEx() for reseting negative + coordinates to 0,0 ; because 'soundrec.exe' give negative values + and I need it to work on MMSYSTEM ... :-) + + * [miscemu/int2f.c] + add a stub 'do_int2f_16' (function 0x16) for DMPI server. + +Mon Jun 20 10:08:40 BST 1994 William Smith (wos@dcs.warwick.ac.uk) + + * include/comm.h + New file -- some definitions that were in comm.c now need to + be shared with misc/dos_fs.c + + * misc/comm.c + Some definitions moved into include/comm.h + + * misc/dos_fs.c (DOS_GetEquipment): + Fixed error in equipment -- bitwise or of two values should + be used instead of logical or. Also added code to correctly + report the number of serial and parallel devices. + ---------------------------------------------------------------------- Mon Jun 20 14:26:41 1994 Bob Amstadt (bob@pooh) diff --git a/controls/edit.c b/controls/edit.c index 3aff8f86934..2a1c12cda31 100644 --- a/controls/edit.c +++ b/controls/edit.c @@ -67,6 +67,8 @@ typedef struct int DeletedLength; /* length of deleted text */ int DeletedCurrLine; /* starting line from which text was deleted */ int DeletedCurrCol; /* starting col from which text was deleted */ + int NumTabStops; /* number of tab stops in buffer hTabStops */ + HANDLE hTabStops; /* handle of tab stops buffer */ } EDITSTATE; @@ -79,6 +81,9 @@ typedef struct #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol) #define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \ es->SelEndLine != 0 || es->SelEndCol != 0) +#define ROUNDUP(numer, denom) ((numer % denom) \ + ? (((numer + denom) / denom) * denom) \ + : numer) /* macros to access window styles */ #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL) @@ -104,14 +109,16 @@ void EDIT_ModTextPointers(HWND hwnd, int lineno, int var); void EDIT_PaintMsg(HWND hwnd); HANDLE EDIT_GetTextLine(HWND hwnd, int selection); char *EDIT_TextLine(HWND hwnd, int sel); -int EDIT_LineLength(EDITSTATE *es, char *str, int len); +int EDIT_StrLength(EDITSTATE *es, char *str, int len, int pcol); +int EDIT_LineLength(HWND hwnd, int num); void EDIT_WriteTextLine(HWND hwnd, RECT *rc, int y); void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row, int col, RECT *rc, BOOL blank, BOOL reverse); HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff); void EDIT_CharMsg(HWND hwnd, WORD wParam); void EDIT_KeyTyped(HWND hwnd, short ch); -int EDIT_CharWidth(EDITSTATE *es, short ch); +int EDIT_CharWidth(EDITSTATE *es, short ch, int pcol); +int EDIT_GetNextTabStop(EDITSTATE *es, int pcol); void EDIT_Forward(HWND hwnd); void EDIT_Downward(HWND hwnd); void EDIT_Upward(HWND hwnd); @@ -162,6 +169,7 @@ unsigned int EDIT_TextAlloc(EDITSTATE *es, int bytes); void *EDIT_TextAddr(EDITSTATE *es, unsigned int handle); unsigned int EDIT_TextReAlloc(EDITSTATE *es, unsigned int handle, int bytes); void EDIT_SetHandleMsg(HWND hwnd, WORD wParam); +LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam); void swap(int *a, int *b); @@ -295,7 +303,7 @@ LONG EditWndProc(HWND hwnd, WORD uMsg, WORD wParam, LONG lParam) break; case EM_SETTABSTOPS: - printf("edit: cannot process EM_SETTABSTOPS message\n"); + lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam); break; case EM_SETWORDBREAKPROC: @@ -451,7 +459,7 @@ long EDIT_NCCreateMsg(HWND hwnd, LONG lParam) /* --- text buffer */ es->localheap = &HEAP_LocalFindHeap(createStruct->hInstance)->free_list; es->MaxTextLen = MAXTEXTLEN + 1; - if (!(es->hText)) + if (!(createStruct->lpszName)) { es->textlen = EditBufLen(wndPtr) + 1; es->hText = EDIT_TextAlloc(es, EditBufLen(wndPtr) + 2); @@ -464,15 +472,18 @@ long EDIT_NCCreateMsg(HWND hwnd, LONG lParam) if (strlen(createStruct->lpszName) < EditBufLen(wndPtr)) { es->hText = EDIT_TextAlloc(es, EditBufLen(wndPtr) + 2); - es->textlen = EditBufLen(wndPtr) + 1; + text = EDIT_TextAddr(es, es->hText); + strcpy(text, createStruct->lpszName); *(text + es->textlen) = '\0'; + es->textlen = EditBufLen(wndPtr) + 1; } else { es->hText = EDIT_TextAlloc(es, strlen(createStruct->lpszName) + 2); + text = EDIT_TextAddr(es, es->hText); + strcpy(text, createStruct->lpszName); es->textlen = strlen(createStruct->lpszName) + 1; } - text = EDIT_TextAddr(es, es->hText); *(text + es->textlen + 1) = '\0'; EDIT_BuildTextPointers(hwnd); } @@ -524,6 +535,8 @@ long EDIT_CreateMsg(HWND hwnd, LONG lParam) es->hFont = 0; es->hDeletedText = 0; es->DeletedLength = 0; + es->NumTabStops = 0; + es->hTabStops = EDIT_HEAP_ALLOC(sizeof(int)); /* allocate space for a line full of blanks to speed up */ /* line filling */ @@ -608,14 +621,15 @@ void EDIT_BuildTextPointers(HWND hwnd) /* advance through current line */ while (*cp && *cp != '\n') { - len += charWidths[*cp]; /* width of line in pixels */ + len += EDIT_CharWidth(es, *cp, len); /* width of line in pixels */ cp++; } es->textwidth = max(es->textwidth, len); if (*cp) cp++; /* skip '\n' */ } - off = (unsigned int)(cp - text); /* offset of beginning of line */ + + off = (unsigned int)(cp - text); *(textPtrs + es->wlines) = off; } @@ -722,26 +736,45 @@ char *EDIT_TextLine(HWND hwnd, int sel) /********************************************************************* - * EDIT_LineLength + * EDIT_StrLength * - * Return length of line _str_ of length _len_ characters in pixels. + * Return length of string _str_ of length _len_ characters in pixels. + * The current column offset in pixels _pcol_ is required to calculate + * the width of a tab. */ -int EDIT_LineLength(EDITSTATE *es, char *str, int len) +int EDIT_StrLength(EDITSTATE *es, char *str, int len, int pcol) { int i, plen = 0; - short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths); for (i = 0; i < len; i++) - plen += charWidths[*(str + i)]; + plen += EDIT_CharWidth(es, *(str + i), pcol + plen); #ifdef DEBUG_EDIT - printf("EDIT_LineLength: returning %d\n", plen); + printf("EDIT_StrLength: returning %d\n", plen); #endif return plen; } +/********************************************************************* + * EDIT_LineLength + * + * Return length of line _num_ in characters. + */ + +int EDIT_LineLength(HWND hwnd, int num) +{ + WND *wndPtr = WIN_FindWndPtr(hwnd); + EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra))); + char *cp = EDIT_TextLine(hwnd, num); + char *cp1; + + cp1 = strchr(cp, '\n'); + return cp1 ? (int)(cp1 - cp) : strlen(cp); +} + + /********************************************************************* * EDIT_WriteTextLine * @@ -812,7 +845,7 @@ void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y) if ((hLine = EDIT_GetTextLine(hwnd, y)) == 0) return; lp = (unsigned char *)EDIT_HEAP_ADDR(hLine); - lnlen = EDIT_LineLength(es, lp, strlen(lp)); + lnlen = EDIT_StrLength(es, lp, strlen(lp), 0); lnlen1 = lnlen; /* build the line to display */ @@ -852,7 +885,7 @@ void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y) TRUE, TRUE); else if (y == sbl) { - col = EDIT_LineLength(es, lp, sbc); + col = EDIT_StrLength(es, lp, sbc, 0); if (col > (es->wleft + rc.left)) { len = min(col - off, rc.right - off); @@ -862,7 +895,7 @@ void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y) } if (y == sel) { - col = EDIT_LineLength(es, lp, sec); + col = EDIT_StrLength(es, lp, sec, 0); if (col < (es->wleft + rc.right)) { len = min(col - off, rc.right - off); @@ -890,7 +923,7 @@ void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y) } else if (y == sel) { - col = EDIT_LineLength(es, lp, sec); + col = EDIT_StrLength(es, lp, sec, 0); if (col < (es->wleft + rc.right)) { len = min(col - off, rc.right - off); @@ -930,14 +963,15 @@ void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row, { HDC hdc; HANDLE hStr; - char *str, *blanks; - int diff, num_spaces; + char *str, *cp, *cp1; + int diff, num_spaces, tabwidth, scol; HRGN hrgnClip; COLORREF oldTextColor, oldBkgdColor; HFONT oldfont; WND *wndPtr = WIN_FindWndPtr(hwnd); EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra))); short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths); + char *blanks = (char *)EDIT_HEAP_ADDR(es->hBlankLine); #ifdef DEBUG_EDIT printf("EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse); @@ -963,7 +997,31 @@ void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row, SetTextColor(hdc, oldBkgdColor); } - TextOut(hdc, col - diff, row * es->txtht, str, strlen(str)); + if (!(cp = strchr(str, VK_TAB))) + TextOut(hdc, col - diff, row * es->txtht, str, strlen(str)); + else + { + TextOut(hdc, col - diff, row * es->txtht, str, (int)(cp - str)); + scol = EDIT_StrLength(es, str, (int)(cp - str), 0); + tabwidth = EDIT_CharWidth(es, VK_TAB, scol); + num_spaces = tabwidth / charWidths[32] + 1; + TextOut(hdc, scol, row * es->txtht, blanks, num_spaces); + cp++; + scol += tabwidth; + + while (cp1 = strchr(cp, VK_TAB)) + { + TextOut(hdc, scol, row * es->txtht, cp, (int)(cp1 - cp)); + scol = EDIT_StrLength(es, cp, (int)(cp1 - cp), scol); + tabwidth = EDIT_CharWidth(es, VK_TAB, scol); + num_spaces = tabwidth / charWidths[32] + 1; + TextOut(hdc, scol, row * es->txtht, blanks, num_spaces); + cp = ++cp1; + scol += tabwidth; + } + + TextOut(hdc, scol, row * es->txtht, cp, strlen(cp)); + } if (reverse) { @@ -976,7 +1034,6 @@ void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row, { if ((rc->right - col) > len) { - blanks = EDIT_HEAP_ADDR(es->hBlankLine); num_spaces = (rc->right - col - len) / charWidths[32]; TextOut(hdc, col + len, row * es->txtht, blanks, num_spaces); } @@ -1003,9 +1060,8 @@ HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff) { HANDLE hStr; char *str; - int ch = 0, i = 0, j, tmp; + int ch = 0, i = 0, j, s_i; int ch1; - short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths); #ifdef DEBUG_EDIT printf("EDIT_GetStr %s %d %d\n", lp, off, len); @@ -1013,19 +1069,23 @@ HANDLE EDIT_GetStr(EDITSTATE *es, char *lp, int off, int len, int *diff) while (i < off) { - i += charWidths[*(lp + ch)]; + s_i = i; + i += EDIT_CharWidth(es, *(lp + ch), i); ch++; } /* if stepped past _off_, go back a character */ if (i - off) - i -= charWidths[*(lp + --ch)]; + { + i = s_i; + ch--; + } *diff = off - i; ch1 = ch; while (i < len + off) { - i += charWidths[*(lp + ch)]; + i += EDIT_CharWidth(es, *(lp + ch), i); ch++; } @@ -1102,7 +1162,7 @@ void EDIT_KeyTyped(HWND hwnd, short ch) return; } - if (*currchar == '\0') + if (*currchar == '\0' && IsMultiLine()) { /* insert a newline at end of text */ *currchar = '\n'; @@ -1145,13 +1205,13 @@ void EDIT_KeyTyped(HWND hwnd, short ch) if (IsMultiLine() && es->wlines > 1) { es->textwidth = max(es->textwidth, - EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine), + EDIT_StrLength(es, EDIT_TextLine(hwnd, es->CurrLine), (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) - - EDIT_TextLine(hwnd, es->CurrLine)))); + EDIT_TextLine(hwnd, es->CurrLine)), 0)); } else es->textwidth = max(es->textwidth, - EDIT_LineLength(es, text, strlen(text))); + EDIT_StrLength(es, text, strlen(text), 0)); EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow); if (ch == '\n') @@ -1177,14 +1237,15 @@ void EDIT_KeyTyped(HWND hwnd, short ch) } /* test end of window */ - if (es->WndCol >= ClientWidth(wndPtr) - EDIT_CharWidth(es, ch)) + if (es->WndCol >= ClientWidth(wndPtr) - + EDIT_CharWidth(es, ch, es->WndCol + es->wleft)) { /* TODO:- Word wrap to be handled here */ /* if (!(currchar == text + es->MaxTextLen - 2)) */ EDIT_KeyHScroll(hwnd, SB_LINEDOWN); } - es->WndCol += EDIT_CharWidth(es, ch); + es->WndCol += EDIT_CharWidth(es, ch, es->WndCol + es->wleft); es->CurrCol++; SetCaretPos(es->WndCol, es->WndRow * es->txtht); ShowCaret(hwnd); @@ -1196,13 +1257,46 @@ void EDIT_KeyTyped(HWND hwnd, short ch) * EDIT_CharWidth * * Return the width of the given character in pixels. + * The current column offset in pixels _pcol_ is required to calculate + * the width of a tab. */ -int EDIT_CharWidth(EDITSTATE *es, short ch) +int EDIT_CharWidth(EDITSTATE *es, short ch, int pcol) { short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths); - return (charWidths[ch]); + if (ch != VK_TAB) + return (charWidths[ch]); + else + return (EDIT_GetNextTabStop(es, pcol) - pcol); +} + + +/********************************************************************* + * EDIT_GetNextTabStop + * + * Return the next tab stop beyond _pcol_. + */ + +int EDIT_GetNextTabStop(EDITSTATE *es, int pcol) +{ + int i; + int baseUnitWidth = LOWORD(GetDialogBaseUnits()); + unsigned short *tabstops = EDIT_HEAP_ADDR(es->hTabStops); + + if (es->NumTabStops == 0) + return ROUNDUP(pcol, 8); + else if (es->NumTabStops == 1) + return ROUNDUP(pcol, *tabstops * baseUnitWidth / 4); + else + { + for (i = 0; i < es->NumTabStops; i++) + { + if (*(tabstops + i) * baseUnitWidth / 4 >= pcol) + return (*(tabstops + i) * baseUnitWidth / 4); + } + return pcol; + } } @@ -1217,9 +1311,8 @@ void EDIT_Forward(HWND hwnd) WND *wndPtr = WIN_FindWndPtr(hwnd); EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra))); char *text = EDIT_TextAddr(es, es->hText); - char *cc = CurrChar + 1; - if (*cc == '\0') + if (*CurrChar == '\0') return; if (*CurrChar == '\n') @@ -1229,7 +1322,7 @@ void EDIT_Forward(HWND hwnd) } else { - es->WndCol += EDIT_CharWidth(es, *CurrChar); + es->WndCol += EDIT_CharWidth(es, *CurrChar, es->WndCol + es->wleft); es->CurrCol++; if (es->WndCol >= ClientWidth(wndPtr)) EDIT_KeyHScroll(hwnd, SB_LINEDOWN); @@ -1309,7 +1402,7 @@ void EDIT_Backward(HWND hwnd) if (es->CurrCol) { --es->CurrCol; - es->WndCol -= EDIT_CharWidth(es, *CurrChar); + es->WndCol -= EDIT_CharWidth(es, *CurrChar, es->WndCol + es->wleft); if (es->WndCol < 0) EDIT_KeyHScroll(hwnd, SB_LINEUP); } @@ -1336,7 +1429,7 @@ void EDIT_End(HWND hwnd) while (*CurrChar && *CurrChar != '\n') { - es->WndCol += EDIT_CharWidth(es, *CurrChar); + es->WndCol += EDIT_CharWidth(es, *CurrChar, es->WndCol + es->wleft); es->CurrCol++; } @@ -1382,15 +1475,13 @@ void EDIT_StickEnd(HWND hwnd) { WND *wndPtr = WIN_FindWndPtr(hwnd); EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra))); + int len = EDIT_LineLength(hwnd, es->CurrLine); + char *cp = EDIT_TextLine(hwnd, es->CurrLine); char currpel; - char *cp = EDIT_TextLine(hwnd, es->CurrLine); - char *cp1 = strchr(cp, '\n'); - int len = cp1 ? (int)(cp1 - cp) : 0; - es->CurrCol = min(len, es->CurrCol); - es->WndCol = min(EDIT_LineLength(es, cp, len) - es->wleft, es->WndCol); - currpel = EDIT_LineLength(es, cp, es->CurrCol); + es->WndCol = min(EDIT_StrLength(es, cp, len, 0) - es->wleft, es->WndCol); + currpel = EDIT_StrLength(es, cp, es->CurrCol, 0); if (es->wleft > currpel) { @@ -1848,7 +1939,6 @@ void EDIT_VScrollLine(HWND hwnd, WORD opt) if (es->wtop + ClientHeight(wndPtr, es) >= es->wlines) return; es->wtop++; - printf("Scroll line down: wtop=%d\n", es->wtop); } else { @@ -1856,7 +1946,6 @@ void EDIT_VScrollLine(HWND hwnd, WORD opt) if (es->wtop == 0) return; --es->wtop; - printf("Scroll line up: wtop=%d\n", es->wtop); } if (IsWindowVisible(hwnd)) @@ -1974,7 +2063,7 @@ void EDIT_SizeMsg(HWND hwnd, WORD wParam, LONG lParam) void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam) { - char *cp, *cp1; + char *cp; int len; BOOL end = FALSE; WND *wndPtr = WIN_FindWndPtr(hwnd); @@ -1995,12 +2084,10 @@ void EDIT_LButtonDownMsg(HWND hwnd, WORD wParam, LONG lParam) es->CurrLine = es->wtop + es->WndRow; cp = EDIT_TextLine(hwnd, es->CurrLine); - cp1 = strchr(cp, '\n'); - len = cp1 ? (int)(cp1 - cp) : 0; - + len = EDIT_LineLength(hwnd, es->CurrLine); es->WndCol = LOWORD(lParam); - if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end) - es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft; + if (es->WndCol > EDIT_StrLength(es, cp, len, 0) - es->wleft || end) + es->WndCol = EDIT_StrLength(es, cp, len, 0) - es->wleft; es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol)); ButtonDown = TRUE; @@ -2040,11 +2127,10 @@ void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam) int EDIT_PixelToChar(HWND hwnd, int row, int *pixel) { - int ch = 0, i = 0; + int ch = 0, i = 0, s_i; char *text; WND *wndPtr = WIN_FindWndPtr(hwnd); EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra))); - short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths); #ifdef DEBUG_EDIT printf("EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel); @@ -2053,13 +2139,17 @@ int EDIT_PixelToChar(HWND hwnd, int row, int *pixel) text = EDIT_TextLine(hwnd, row); while (i < *pixel) { - i += charWidths[*(text + ch)]; + s_i = i; + i += EDIT_CharWidth(es, *(text + ch), i); ch++; } /* if stepped past _pixel_, go back a character */ if (i - *pixel) - i -= charWidths[*(text + ch)]; + { + i = s_i; + --ch; + } *pixel = i; return ch; } @@ -2154,8 +2244,8 @@ void EDIT_SetSelMsg(HWND hwnd, LONG lParam) es->wtop = es->SelEndLine; es->WndRow = 0; } - es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->SelEndLine), - es->SelEndCol) - es->wleft; + es->WndCol = EDIT_StrLength(es, EDIT_TextLine(hwnd, es->SelEndLine), + es->SelEndCol, 0) - es->wleft; } InvalidateRect(hwnd, NULL, TRUE); UpdateWindow(hwnd); @@ -2202,8 +2292,10 @@ void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col) } *line = lineno - 1; *col = off - (int)(cp1 - text); +#if 0 if (*(text + *col) == '\0') (*col)--; +#endif } @@ -2238,8 +2330,8 @@ void EDIT_DeleteSel(HWND hwnd) es->wtop = es->SelBegLine; es->WndRow = 0; } - es->WndCol = EDIT_LineLength(es, bbl - es->SelBegCol, - es->SelBegCol) - es->wleft; + es->WndCol = EDIT_StrLength(es, bbl - es->SelBegCol, + es->SelBegCol, 0) - es->wleft; EDIT_BuildTextPointers(hwnd); es->PaintBkgd = TRUE; @@ -2329,7 +2421,7 @@ void EDIT_SetAnchor(HWND hwnd, int row, int col) void EDIT_ExtendSel(HWND hwnd, int x, int y) { int bbl, bel, bbc, bec; - char *cp, *cp1; + char *cp; int len; BOOL end = FALSE; WND *wndPtr = WIN_FindWndPtr(hwnd); @@ -2342,8 +2434,7 @@ void EDIT_ExtendSel(HWND hwnd, int x, int y) bbl = es->SelEndLine; bbc = es->SelEndCol; cp = EDIT_TextLine(hwnd, es->wtop + y / es->txtht); - cp1 = strchr(cp, '\n'); - len = cp1 ? (int)(cp1 - cp) : 0; + len = EDIT_LineLength(hwnd, es->wtop + y / es->txtht); es->WndRow = y / es->txtht; if (es->WndRow > es->wlines - es->wtop - 1) @@ -2358,8 +2449,8 @@ void EDIT_ExtendSel(HWND hwnd, int x, int y) es->SelEndLine = es->CurrLine; es->WndCol = x; - if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end) - es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft; + if (es->WndCol > EDIT_StrLength(es, cp, len, 0) - es->wleft || end) + es->WndCol = EDIT_StrLength(es, cp, len, 0) - es->wleft; es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol)); es->SelEndCol = es->CurrCol - 1; @@ -2404,7 +2495,7 @@ void EDIT_WriteSel(HWND hwnd, int y, int start, int end) { RECT rc; int scol, ecol; - char *cp, *cp1; + char *cp; HDC hdc; HBRUSH hbrush, holdbrush; int olddm; @@ -2425,15 +2516,12 @@ void EDIT_WriteSel(HWND hwnd, int y, int start, int end) /* get length of line if end == -1 */ if (end == -1) - { - cp1 = strchr(cp, '\n'); - end = cp1 ? (int)(cp1 - cp) : 0; - } + end = EDIT_LineLength(hwnd, y); - scol = EDIT_LineLength(es, cp, start); + scol = EDIT_StrLength(es, cp, start, 0); if (scol > rc.right) return; if (scol < rc.left) scol = rc.left; - ecol = EDIT_LineLength(es, cp, end); + ecol = EDIT_StrLength(es, cp, end, 0); if (ecol < rc.left) return; if (ecol > rc.right) ecol = rc.right; @@ -2551,8 +2639,8 @@ void EDIT_InsertText(HWND hwnd, char *str, int len) EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine), &(es->CurrCol)); es->WndRow = es->CurrLine - es->wtop; - es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine), - es->CurrCol) - es->wleft; + es->WndCol = EDIT_StrLength(es, EDIT_TextLine(hwnd, es->CurrLine), + es->CurrCol, 0) - es->wleft; } @@ -2669,8 +2757,8 @@ void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam) ReleaseDC(hwnd, hdc); es->WndRow = (es->CurrLine - es->wtop) / es->txtht; - es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine), - es->CurrCol) - es->wleft; + es->WndCol = EDIT_StrLength(es, EDIT_TextLine(hwnd, es->CurrLine), + es->CurrCol, 0) - es->wleft; InvalidateRect(hwnd, NULL, TRUE); es->PaintBkgd = TRUE; @@ -2741,8 +2829,8 @@ LONG EDIT_UndoMsg(HWND hwnd) EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text), &(es->CurrLine), &(es->CurrCol)); es->WndRow = es->CurrLine - es->wtop; - es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine), - es->CurrCol) - es->wleft; + es->WndCol = EDIT_StrLength(es, EDIT_TextLine(hwnd, es->CurrLine), + es->CurrCol, 0) - es->wleft; es->SelEndLine = es->CurrLine; es->SelEndCol = es->CurrCol; @@ -2825,6 +2913,35 @@ void EDIT_SetHandleMsg(HWND hwnd, WORD wParam) } +/********************************************************************* + * EM_SETTABSTOPS message function + */ + +LONG EDIT_SetTabStopsMsg(HWND hwnd, WORD wParam, LONG lParam) +{ + unsigned short *tabstops; + WND *wndPtr = WIN_FindWndPtr(hwnd); + EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra))); + + es->NumTabStops = wParam; + if (wParam == 0) + es->hTabStops = EDIT_HEAP_REALLOC(es->hTabStops, 1); + else if (wParam == 1) + { + es->hTabStops = EDIT_HEAP_REALLOC(es->hTabStops, 1); + tabstops = (unsigned short *)EDIT_HEAP_ADDR(es->hTabStops); + *tabstops = (unsigned short)lParam; + } + else + { + es->hTabStops = EDIT_HEAP_REALLOC(es->hTabStops, wParam); + tabstops = (unsigned short *)EDIT_HEAP_ADDR(es->hTabStops); + memcpy(tabstops, (unsigned short *)lParam, wParam); + } + return 0L; +} + + /********************************************************************* * Utility functions */ diff --git a/controls/listbox.c b/controls/listbox.c index 196cb9bdb01..8b7af561aa5 100644 --- a/controls/listbox.c +++ b/controls/listbox.c @@ -1151,7 +1151,7 @@ int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec) { if (DOS_ValidDrive(x)) { - sprintf(temp, "[-%c-]", 'A'+x); + sprintf(temp, "[-%c-]", 'a'+x); if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break; } diff --git a/include/comm.h b/include/comm.h new file mode 100644 index 00000000000..7f746857332 --- /dev/null +++ b/include/comm.h @@ -0,0 +1,21 @@ +/* + * Communications header + * + * 93 Erik Bos (erik@trashcan.hacktic.nl) + */ + +#ifndef COMM_H +#define COMM_H + + +#define MAX_PORTS 16 + +struct DosDeviceStruct { + char *devicename; /* /dev/cua1 */ + int fd; + int suspended; + int unget; + int unget_byte; +}; + +#endif /* COMM_H */ diff --git a/include/mmsystem.h b/include/mmsystem.h index de39b93874e..feb2eda5614 100644 --- a/include/mmsystem.h +++ b/include/mmsystem.h @@ -8,6 +8,11 @@ typedef LPSTR HPSTR; /* a huge version of LPSTR */ typedef LPCSTR HPCSTR; /* a huge version of LPCSTR */ +#define MAXWAVEDRIVERS 10 +#define MAXMIDIDRIVERS 10 +#define MAXAUXDRIVERS 10 +#define MAXMCIDRIVERS 32 + #define MAXPNAMELEN 32 /* max product name length (including NULL) */ #define MAXERRORLENGTH 128 /* max error text length (including NULL) */ @@ -166,7 +171,7 @@ typedef WAVECALLBACK FAR *LPWAVECALLBACK; #define WAVE_FORMAT_QUERY 0x0001 #define WAVE_ALLOWSYNC 0x0002 -typedef struct { +typedef struct wavehdr_tag { LPSTR lpData; /* pointer to locked data buffer */ DWORD dwBufferLength; /* length of data buffer */ DWORD dwBytesRecorded; /* used for input only */ @@ -764,8 +769,10 @@ YIELDPROC WINAPI mciGetYieldProc (UINT uDeviceID, DWORD FAR* lpdwYieldData); #define MCIERR_CUSTOM_DRIVER_BASE (MCIERR_BASE + 256) -#define MCI_OPEN 0x0803 -#define MCI_CLOSE 0x0804 +#define MCI_OPEN_DRIVER 0x0801 +#define MCI_CLOSE_DRIVER 0x0802 +#define MCI_OPEN 0x0803 +#define MCI_CLOSE 0x0804 #define MCI_ESCAPE 0x0805 #define MCI_PLAY 0x0806 #define MCI_SEEK 0x0807 @@ -1389,6 +1396,126 @@ typedef MCI_OVLY_LOAD_PARMS FAR * LPMCI_OVLY_LOAD_PARMS; * Linux MMSYSTEM Internals & Sample Audio Drivers */ +#define DRVM_INIT 100 +#define WODM_INIT DRVM_INIT +#define WIDM_INIT DRVM_INIT +#define MODM_INIT DRVM_INIT +#define MIDM_INIT DRVM_INIT +#define AUXM_INIT DRVM_INIT + +#define WODM_GETNUMDEVS 3 +#define WODM_GETDEVCAPS 4 +#define WODM_OPEN 5 +#define WODM_CLOSE 6 +#define WODM_PREPARE 7 +#define WODM_UNPREPARE 8 +#define WODM_WRITE 9 +#define WODM_PAUSE 10 +#define WODM_RESTART 11 +#define WODM_RESET 12 +#define WODM_GETPOS 13 +#define WODM_GETPITCH 14 +#define WODM_SETPITCH 15 +#define WODM_GETVOLUME 16 +#define WODM_SETVOLUME 17 +#define WODM_GETPLAYBACKRATE 18 +#define WODM_SETPLAYBACKRATE 19 +#define WODM_BREAKLOOP 20 + +#define WIDM_GETNUMDEVS 50 +#define WIDM_GETDEVCAPS 51 +#define WIDM_OPEN 52 +#define WIDM_CLOSE 53 +#define WIDM_PREPARE 54 +#define WIDM_UNPREPARE 55 +#define WIDM_ADDBUFFER 56 +#define WIDM_START 57 +#define WIDM_STOP 58 +#define WIDM_RESET 59 +#define WIDM_GETPOS 60 + +#define MODM_GETNUMDEVS 1 +#define MODM_GETDEVCAPS 2 +#define MODM_OPEN 3 +#define MODM_CLOSE 4 +#define MODM_PREPARE 5 +#define MODM_UNPREPARE 6 +#define MODM_DATA 7 +#define MODM_LONGDATA 8 +#define MODM_RESET 9 +#define MODM_GETVOLUME 10 +#define MODM_SETVOLUME 11 +#define MODM_CACHEPATCHES 12 +#define MODM_CACHEDRUMPATCHES 13 + +#define MIDM_GETNUMDEVS 53 +#define MIDM_GETDEVCAPS 54 +#define MIDM_OPEN 55 +#define MIDM_CLOSE 56 +#define MIDM_PREPARE 57 +#define MIDM_UNPREPARE 58 +#define MIDM_ADDBUFFER 59 +#define MIDM_START 60 +#define MIDM_STOP 61 +#define MIDM_RESET 62 + +#define AUXDM_GETNUMDEVS 3 +#define AUXDM_GETDEVCAPS 4 +#define AUXDM_GETVOLUME 5 +#define AUXDM_SETVOLUME 6 + +#define MCI_MAX_DEVICE_TYPE_LENGTH 80 + +#define MCI_FALSE (MCI_STRING_OFFSET + 19) +#define MCI_TRUE (MCI_STRING_OFFSET + 20) + +#define MCI_FORMAT_RETURN_BASE MCI_FORMAT_MILLISECONDS_S +#define MCI_FORMAT_MILLISECONDS_S (MCI_STRING_OFFSET + 21) +#define MCI_FORMAT_HMS_S (MCI_STRING_OFFSET + 22) +#define MCI_FORMAT_MSF_S (MCI_STRING_OFFSET + 23) +#define MCI_FORMAT_FRAMES_S (MCI_STRING_OFFSET + 24) +#define MCI_FORMAT_SMPTE_24_S (MCI_STRING_OFFSET + 25) +#define MCI_FORMAT_SMPTE_25_S (MCI_STRING_OFFSET + 26) +#define MCI_FORMAT_SMPTE_30_S (MCI_STRING_OFFSET + 27) +#define MCI_FORMAT_SMPTE_30DROP_S (MCI_STRING_OFFSET + 28) +#define MCI_FORMAT_BYTES_S (MCI_STRING_OFFSET + 29) +#define MCI_FORMAT_SAMPLES_S (MCI_STRING_OFFSET + 30) +#define MCI_FORMAT_TMSF_S (MCI_STRING_OFFSET + 31) + +#define MCI_VD_FORMAT_TRACK_S (MCI_VD_OFFSET + 5) + +#define WAVE_FORMAT_PCM_S (MCI_WAVE_OFFSET + 0) +#define WAVE_MAPPER_S (MCI_WAVE_OFFSET + 1) + +#define MCI_SEQ_MAPPER_S (MCI_SEQ_OFFSET + 5) +#define MCI_SEQ_FILE_S (MCI_SEQ_OFFSET + 6) +#define MCI_SEQ_MIDI_S (MCI_SEQ_OFFSET + 7) +#define MCI_SEQ_SMPTE_S (MCI_SEQ_OFFSET + 8) +#define MCI_SEQ_FORMAT_SONGPTR_S (MCI_SEQ_OFFSET + 9) +#define MCI_SEQ_NONE_S (MCI_SEQ_OFFSET + 10) +#define MIDIMAPPER_S (MCI_SEQ_OFFSET + 11) + +#define MCI_RESOURCE_RETURNED 0x00010000 /* resource ID */ +#define MCI_COLONIZED3_RETURN 0x00020000 /* colonized ID, 3 bytes data */ +#define MCI_COLONIZED4_RETURN 0x00040000 /* colonized ID, 4 bytes data */ +#define MCI_INTEGER_RETURNED 0x00080000 /* integer conversion needed */ +#define MCI_RESOURCE_DRIVER 0x00100000 /* driver owns returned resource */ + +#define MCI_NO_COMMAND_TABLE 0xFFFF + +#define MCI_COMMAND_HEAD 0 +#define MCI_STRING 1 +#define MCI_INTEGER 2 +#define MCI_END_COMMAND 3 +#define MCI_RETURN 4 +#define MCI_FLAG 5 +#define MCI_END_COMMAND_LIST 6 +#define MCI_RECT 7 +#define MCI_CONSTANT 8 +#define MCI_END_CONSTANT 9 + +#define MAKEMCIRESOURCE(wRet, wRes) MAKELRESULT((wRet), (wRes)) + typedef struct { DWORD dwCallback; DWORD dwInstance; @@ -1397,6 +1524,56 @@ typedef struct { } PORTALLOC; typedef PORTALLOC FAR *LPPORTALLOC; +typedef struct { + HWAVE hWave; + LPWAVEFORMAT lpFormat; + DWORD dwCallBack; + DWORD dwInstance; + } WAVEOPENDESC; +typedef WAVEOPENDESC FAR *LPWAVEOPENDESC; + +typedef struct { + HMIDI hMidi; + DWORD dwCallback; + DWORD dwInstance; + } MIDIOPENDESC; +typedef MIDIOPENDESC FAR *LPMIDIOPENDESC; + +typedef struct { + UINT wDelay; + UINT wResolution; + LPTIMECALLBACK lpFunction; + DWORD dwUser; + UINT wFlags; + } TIMEREVENT; +typedef TIMEREVENT FAR *LPTIMEREVENT; + +typedef struct { + UINT wDeviceID; /* device ID */ + LPSTR lpstrParams; /* parameter string for entry in SYSTEM.INI */ + UINT wCustomCommandTable; /* custom command table (0xFFFF if none) */ + /* filled in by the driver */ + UINT wType; /* driver type */ + /* filled in by the driver */ + } MCI_OPEN_DRIVER_PARMS; +typedef MCI_OPEN_DRIVER_PARMS FAR * LPMCI_OPEN_DRIVER_PARMS; + +DWORD WINAPI mciGetDriverData(UINT uDeviceID); +BOOL WINAPI mciSetDriverData(UINT uDeviceID, DWORD dwData); +UINT WINAPI mciDriverYield(UINT uDeviceID); +BOOL WINAPI mciDriverNotify(HWND hwndCallback, UINT uDeviceID, + UINT uStatus); +UINT WINAPI mciLoadCommandResource(HINSTANCE hInstance, + LPCSTR lpResName, UINT uType); +BOOL WINAPI mciFreeCommandResource(UINT uTable); + +#define DCB_NULL 0x0000 +#define DCB_WINDOW 0x0001 /* dwCallback is a HWND */ +#define DCB_TASK 0x0002 /* dwCallback is a HTASK */ +#define DCB_FUNCTION 0x0003 /* dwCallback is a FARPROC */ +#define DCB_TYPEMASK 0x0007 +#define DCB_NOSWITCH 0x0008 /* don't switch stacks for callback */ + BOOL DriverCallback(DWORD dwCallBack, UINT uFlags, HANDLE hDev, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2); DWORD auxMessage(WORD wDevID, WORD wMsg, DWORD dwUser, diff --git a/include/options.h b/include/options.h index 5003b9fa283..3caf1fd24ab 100644 --- a/include/options.h +++ b/include/options.h @@ -15,7 +15,6 @@ struct options int usePrivateMap; int synchronous; int nobackingstore; - int nosaveunders; short cmdShow; int relay_debug; int debug; diff --git a/include/windows.h b/include/windows.h index 5281abd12ab..c3894553d94 100644 --- a/include/windows.h +++ b/include/windows.h @@ -2790,8 +2790,8 @@ Fb(void,ValidateRgn,HWND,a,HRGN,b) Fc(BOOL,LineTo,HDC,a,short,b,short,c) Fc(WORD,GetInternalWindowPos,HWND,a,LPRECT,b,LPPOINT,c) Fc(LONG,_llseek,INT,a,LONG,b,INT,c) -Fc(INT,_lread,INT,a,LPSTR,b,INT,c) -Fc(INT,_lwrite,INT,a,LPSTR,b,INT,c) +Fc(INT,_lread,INT,a,LPSTR,b,WORD,c) +Fc(INT,_lwrite,INT,a,LPSTR,b,WORD,c) Fc(int,FillRect,HDC,a,LPRECT,b,HBRUSH,c) Fc(DWORD,MoveTo,HDC,a,short,b,short,c) Fc(BOOL,CheckMenuItem,HMENU,a,WORD,b,WORD,c) diff --git a/loader/main.c b/loader/main.c index 8161854eb72..459e7bc181b 100644 --- a/loader/main.c +++ b/loader/main.c @@ -264,7 +264,10 @@ int _WinMain(int argc, char **argv) strncpy(filename, Argv[0], p - Argv[0]); filename[p - Argv[0]] = '\0'; strcat(WindowsPath, ";"); - strcat(WindowsPath, filename); + if (strchr(filename, '/')) + strcat(WindowsPath, GetDosFileName(filename)); + else + strcat(WindowsPath, filename); } if ((hInstMain = LoadImage(Argv[0], EXE, 1)) < 32) { diff --git a/misc/Imakefile b/misc/Imakefile index 59670316267..09d194cc75c 100644 --- a/misc/Imakefile +++ b/misc/Imakefile @@ -16,7 +16,9 @@ SRCS = \ keyboard.c \ lstr.c \ main.c \ + mcicda.c \ message.c \ + mmaux.c \ mmsystem.c \ network.c \ profile.c \ diff --git a/misc/audio.c b/misc/audio.c index 008029f1a91..153223fe436 100644 --- a/misc/audio.c +++ b/misc/audio.c @@ -4,20 +4,109 @@ * Copyright 1994 Martin Ayotte */ +#define DEBUG_MCIWAVE + static char Copyright[] = "Copyright Martin Ayotte, 1994"; #include "stdio.h" -#include "windows.h" #include "win.h" #include "user.h" #include "driver.h" #include "mmsystem.h" +#include +#include +#include + +#define SOUND_DEV "/dev/dsp" + +#ifdef SOUND_VERSION +#define IOCTL(a,b,c) ioctl(a,b,&c) +#else +#define IOCTL(a,b,c) (c = ioctl(a,b,c) ) +#endif + +#define MAX_WAVOUTDRV 2 +#define MAX_WAVINDRV 2 +#define MAX_MCIWAVDRV 2 + +typedef struct { + int unixdev; + int state; + DWORD bufsize; + WAVEOPENDESC waveDesc; + WORD wFlags; + PCMWAVEFORMAT Format; + LPWAVEHDR lpQueueHdr; + DWORD dwTotalPlayed; + } LINUX_WAVEOUT; + +typedef struct { + int unixdev; + int state; + DWORD bufsize; /* Linux '/dev/dsp' give us that size */ + WAVEOPENDESC waveDesc; + WORD wFlags; + PCMWAVEFORMAT Format; + LPWAVEHDR lpQueueHdr; + DWORD dwTotalRecorded; + } LINUX_WAVEIN; + +typedef struct { + int nUseCount; /* Incremented for each shared open */ + BOOL fShareable; /* TRUE if first open was shareable */ + WORD wNotifyDeviceID; /* MCI device ID with a pending notification */ + HANDLE hCallback; /* Callback handle for pending notification */ + int hFile; /* file handle open as Element */ + MCI_WAVE_OPEN_PARMS openParms; + PCMWAVEFORMAT WaveFormat; + WAVEHDR WaveHdr; + } LINUX_MCIWAVE; + +static LINUX_WAVEOUT WOutDev[MAX_WAVOUTDRV]; +static LINUX_WAVEIN WInDev[MAX_WAVOUTDRV]; +static LINUX_MCIWAVE MCIWavDev[MAX_MCIWAVDRV]; + +DWORD WAVE_mciOpen(DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms); +DWORD WAVE_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms); +DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms); +DWORD WAVE_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms); +DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms); +DWORD WAVE_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms); +DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms); +DWORD WAVE_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms); +DWORD WAVE_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms); +DWORD WAVE_mciGetDevCaps(UINT wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpParms); +DWORD WAVE_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms); + +DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize); +DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags); +DWORD wodClose(WORD wDevID); +DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize); +DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize); +DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize); + + +/************************************************************************** +* WAVE_NotifyClient [internal] +*/ +DWORD WAVE_NotifyClient(UINT wDevID, WORD wMsg, + DWORD dwParam1, DWORD dwParam2) +{ + if (WInDev[wDevID].wFlags != DCB_NULL && !DriverCallback( + WInDev[wDevID].waveDesc.dwCallBack, WInDev[wDevID].wFlags, + WInDev[wDevID].waveDesc.hWave, wMsg, + WInDev[wDevID].waveDesc.dwInstance, dwParam1, dwParam2)) { + printf("WAVE_NotifyClient // can't notify client !\n"); + return MMSYSERR_NOERROR; + } +} + /************************************************************************** * AUDIO_DriverProc [sample driver] */ -LRESULT AUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, +LRESULT WAVE_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, DWORD dwParam1, DWORD dwParam2) { switch(wMsg) { @@ -43,17 +132,1320 @@ LRESULT AUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, return (LRESULT)DRVCNF_RESTART; case DRV_REMOVE: return (LRESULT)DRVCNF_RESTART; + case MCI_OPEN_DRIVER: + case MCI_OPEN: + return WAVE_mciOpen(dwParam1, (LPMCI_WAVE_OPEN_PARMS)dwParam2); + case MCI_CLOSE_DRIVER: + case MCI_CLOSE: + return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2); + case MCI_PLAY: + return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2); + case MCI_RECORD: + return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)dwParam2); + case MCI_STOP: + return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2); + case MCI_SET: + return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2); + case MCI_PAUSE: + return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2); + case MCI_RESUME: + return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2); + case MCI_STATUS: + return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2); + case MCI_GETDEVCAPS: + return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2); + case MCI_INFO: + return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS)dwParam2); default: return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); } } +/************************************************************************** +* WAVE_mciOpen */ +DWORD WAVE_mciOpen(DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms) +{ + int hFile; + UINT wDevID; + OFSTRUCT OFstruct; + LPPCMWAVEFORMAT lpWaveFormat; + WAVEOPENDESC WaveDesc; + DWORD dwRet; + char str[128]; + LPSTR ptr; +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciOpen(%08X, %08X)\n", dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + wDevID = lpParms->wDeviceID; + if (MCIWavDev[wDevID].nUseCount > 0) { + /* The driver already open on this channel */ + /* If the driver was opened shareable before and this open specifies */ + /* shareable then increment the use count */ + if (MCIWavDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE)) + ++MCIWavDev[wDevID].nUseCount; + else + return MCIERR_MUST_USE_SHAREABLE; + } + else { + MCIWavDev[wDevID].nUseCount = 1; + MCIWavDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE; + } + if (dwFlags & MCI_OPEN_ELEMENT) { + printf("WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n", + lpParms->lpstrElementName); + printf("WAVE_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); + if (strlen(lpParms->lpstrElementName) > 0) { + strcpy(str, lpParms->lpstrElementName); + AnsiUpper(str); + MCIWavDev[wDevID].hFile = _lopen(str, OF_READWRITE); + if (MCIWavDev[wDevID].hFile < 1) { + MCIWavDev[wDevID].hFile = 0; + printf("WAVE_mciOpen // can't find file='%s' !\n", str); + return MCIERR_FILE_NOT_FOUND; + } + } + else + MCIWavDev[wDevID].hFile = 0; + } + printf("WAVE_mciOpen // hFile=%u\n", MCIWavDev[wDevID].hFile); + memcpy(&MCIWavDev[wDevID].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS)); + MCIWavDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID; + lpWaveFormat = &MCIWavDev[wDevID].WaveFormat; + WaveDesc.hWave = 0; + WaveDesc.lpFormat = (LPWAVEFORMAT)lpWaveFormat; + lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM; + lpWaveFormat->wBitsPerSample = 8; + lpWaveFormat->wf.nChannels = 1; + lpWaveFormat->wf.nSamplesPerSec = 11025; + lpWaveFormat->wf.nAvgBytesPerSec = 11025; + lpWaveFormat->wf.nBlockAlign = 1; + dwRet = wodMessage(0, WODM_OPEN, 0, (DWORD)&WaveDesc, CALLBACK_NULL); + dwRet = widMessage(0, WIDM_OPEN, 0, (DWORD)&WaveDesc, CALLBACK_NULL); + return 0; +} + +/************************************************************************** +* WAVE_mciClose [internal] +*/ +DWORD WAVE_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms) +{ + DWORD dwRet; +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciClose(%u, %08X, %08X);\n", wDevID, dwParam, lpParms); +#endif + MCIWavDev[wDevID].nUseCount--; + if (MCIWavDev[wDevID].nUseCount == 0) { + if (MCIWavDev[wDevID].hFile != 0) { + close(MCIWavDev[wDevID].hFile); + MCIWavDev[wDevID].hFile = 0; + } + dwRet = wodMessage(0, WODM_CLOSE, 0, 0L, 0L); + if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL; + dwRet = widMessage(0, WIDM_CLOSE, 0, 0L, 0L); + if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL; + } + return 0; +} + + +/************************************************************************** +* WAVE_mciPlay [internal] +*/ +DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) +{ + int count; + int start, end; + LPWAVEHDR lpWaveHdr; + DWORD dwRet; +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciPlay(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (MCIWavDev[wDevID].hFile == 0) { + printf("WAVE_mciPlay // can't find file='%s' !\n", + MCIWavDev[wDevID].openParms.lpstrElementName); + return MCIERR_FILE_NOT_FOUND; + } + start = 1; end = 99999; + if (dwFlags & MCI_FROM) { + start = lpParms->dwFrom; + printf("WAVE_mciPlay // MCI_FROM=%d \n", start); + } + if (dwFlags & MCI_TO) { + end = lpParms->dwTo; + printf("WAVE_mciPlay // MCI_TO=%d \n", end); + } +/* + if (dwFlags & MCI_NOTIFY) { + printf("WAVE_mciPlay // MCI_NOTIFY %08X !\n", lpParms->dwCallback); + switch(fork()) { + case -1: + printf("WAVE_mciPlay // Can't 'fork' process !\n"); + break; + case 0: + break; + default: + printf("WAVE_mciPlay // process started ! return to caller...\n"); + return 0; + } + } +*/ + lpWaveHdr = &MCIWavDev[wDevID].WaveHdr; + lpWaveHdr->lpData = (LPSTR) malloc(64000); + lpWaveHdr->dwBufferLength = 32000; + lpWaveHdr->dwUser = 0L; + lpWaveHdr->dwFlags = 0L; + lpWaveHdr->dwLoops = 0L; + dwRet = wodMessage(0, WODM_PREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR)); + printf("WAVE_mciPlay // after WODM_PREPARE \n"); + while(TRUE) { +/* printf("WAVE_mciPlay // before 'read' hFile=%u lpData=%08X dwBufferLength=%u\n", + MCIWavDev[wDevID].hFile, lpWaveHdr->lpData, lpWaveHdr->dwBufferLength); */ + count = _lread(MCIWavDev[wDevID].hFile, lpWaveHdr->lpData, lpWaveHdr->dwBufferLength); + if (count < 1) break; + lpWaveHdr->dwBytesRecorded = count; + printf("WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%08X dwBytesRecorded=%u\n", + lpWaveHdr, lpWaveHdr->dwBytesRecorded); + dwRet = wodMessage(0, WODM_WRITE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR)); + } + printf("WAVE_mciPlay // before WODM_UNPREPARE \n"); + dwRet = wodMessage(0, WODM_UNPREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR)); + printf("WAVE_mciPlay // after WODM_UNPREPARE \n"); + if (lpWaveHdr->lpData != NULL) { + free(lpWaveHdr->lpData); + lpWaveHdr->lpData = NULL; + } + if (dwFlags & MCI_NOTIFY) { +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); +#endif + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + + +/************************************************************************** +* WAVE_mciRecord [internal] +*/ +DWORD WAVE_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms) +{ + int count; + int start, end; + LPWAVEHDR lpWaveHdr; + DWORD dwRet; +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciRecord(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (MCIWavDev[wDevID].hFile == 0) { + printf("WAVE_mciRecord // can't find file='%s' !\n", + MCIWavDev[wDevID].openParms.lpstrElementName); + return MCIERR_FILE_NOT_FOUND; + } + start = 1; end = 99999; + if (dwFlags & MCI_FROM) { + start = lpParms->dwFrom; + printf("WAVE_mciRecord // MCI_FROM=%d \n", start); + } + if (dwFlags & MCI_TO) { + end = lpParms->dwTo; + printf("WAVE_mciRecord // MCI_TO=%d \n", end); + } + lpWaveHdr = &MCIWavDev[wDevID].WaveHdr; + lpWaveHdr->lpData = (LPSTR) malloc(64000); + lpWaveHdr->dwBufferLength = 32000; + lpWaveHdr->dwUser = 0L; + lpWaveHdr->dwFlags = 0L; + lpWaveHdr->dwLoops = 0L; + dwRet = widMessage(0, WIDM_PREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR)); + printf("WAVE_mciRecord // after WIDM_PREPARE \n"); + while(TRUE) { + lpWaveHdr->dwBytesRecorded = 0; + dwRet = widMessage(0, WIDM_START, 0, 0L, 0L); + printf("WAVE_mciRecord // after WIDM_START lpWaveHdr=%08X dwBytesRecorded=%u\n", + lpWaveHdr, lpWaveHdr->dwBytesRecorded); + if (lpWaveHdr->dwBytesRecorded == 0) break; + } + printf("WAVE_mciRecord // before WIDM_UNPREPARE \n"); + dwRet = widMessage(0, WIDM_UNPREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR)); + printf("WAVE_mciRecord // after WIDM_UNPREPARE \n"); + if (lpWaveHdr->lpData != NULL) { + free(lpWaveHdr->lpData); + lpWaveHdr->lpData = NULL; + } + if (dwFlags & MCI_NOTIFY) { +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); +#endif + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + + +/************************************************************************** +* WAVE_mciStop [internal] +*/ +DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) +{ +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciStop(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + return 0; +} + + +/************************************************************************** +* WAVE_mciPause [internal] +*/ +DWORD WAVE_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) +{ +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciPause(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + return 0; +} + + +/************************************************************************** +* WAVE_mciResume [internal] +*/ +DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) +{ +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciResume(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + return 0; +} + + +/************************************************************************** +* WAVE_mciSet [internal] +*/ +DWORD WAVE_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms) +{ +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciSet(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciSet // dwTimeFormat=%08X\n", lpParms->dwTimeFormat); + printf("WAVE_mciSet // dwAudio=%08X\n", lpParms->dwAudio); +#endif + if (dwFlags & MCI_SET_TIME_FORMAT) { + switch (lpParms->dwTimeFormat) { + case MCI_FORMAT_MILLISECONDS: + printf("WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n"); + break; + case MCI_FORMAT_BYTES: + printf("WAVE_mciSet // MCI_FORMAT_BYTES !\n"); + break; + case MCI_FORMAT_SAMPLES: + printf("WAVE_mciSet // MCI_FORMAT_SAMPLES !\n"); + break; + default: + printf("WAVE_mciSet // bad time format !\n"); + return MCIERR_BAD_TIME_FORMAT; + } + } + if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION; + if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION; + if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION; + if (dwFlags & MCI_SET_AUDIO) { + printf("WAVE_mciSet // MCI_SET_AUDIO !\n"); + } + if (dwFlags && MCI_SET_ON) { + printf("WAVE_mciSet // MCI_SET_ON !\n"); + if (dwFlags && MCI_SET_AUDIO_LEFT) { + printf("WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n"); + } + if (dwFlags && MCI_SET_AUDIO_RIGHT) { + printf("WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n"); + } + } + if (dwFlags & MCI_SET_OFF) { + printf("WAVE_mciSet // MCI_SET_OFF !\n"); + } + if (dwFlags & MCI_WAVE_INPUT) { + printf("WAVE_mciSet // MCI_WAVE_INPUT !\n"); + } + if (dwFlags & MCI_WAVE_OUTPUT) { + printf("WAVE_mciSet // MCI_WAVE_OUTPUT !\n"); + } + if (dwFlags & MCI_WAVE_SET_ANYINPUT) { + printf("WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n"); + } + if (dwFlags & MCI_WAVE_SET_ANYOUTPUT) { + printf("WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n"); + } + if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC) { + printf("WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n"); + } + if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE) { + printf("WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n"); + } + if (dwFlags & MCI_WAVE_SET_BLOCKALIGN) { + printf("WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n"); + } + if (dwFlags & MCI_WAVE_SET_CHANNELS) { + printf("WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n"); + } + if (dwFlags & MCI_WAVE_SET_FORMATTAG) { + printf("WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n"); + } + if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC) { + printf("WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n"); + } + return 0; +} + + +/************************************************************************** +* WAVE_mciStatus [internal] +*/ +DWORD WAVE_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms) +{ +#ifdef DEBUG_MCIWAVE + printf("WAVE_mciStatus(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + if (dwFlags & MCI_STATUS_ITEM) { + switch(lpParms->dwItem) { + case MCI_STATUS_CURRENT_TRACK: + lpParms->dwReturn = 1; + break; + case MCI_STATUS_LENGTH: + lpParms->dwReturn = 5555; + if (dwFlags & MCI_TRACK) { + lpParms->dwTrack = 1; + lpParms->dwReturn = 2222; + } + break; + case MCI_STATUS_MODE: + lpParms->dwReturn = MCI_MODE_STOP; + break; + case MCI_STATUS_MEDIA_PRESENT: + printf("WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n"); + lpParms->dwReturn = TRUE; + break; + case MCI_STATUS_NUMBER_OF_TRACKS: + lpParms->dwReturn = 1; + break; + case MCI_STATUS_POSITION: + lpParms->dwReturn = 3333; + if (dwFlags & MCI_STATUS_START) { + lpParms->dwItem = 1; + } + if (dwFlags & MCI_TRACK) { + lpParms->dwTrack = 1; + lpParms->dwReturn = 777; + } + break; + case MCI_STATUS_READY: + printf("WAVE_mciStatus // MCI_STATUS_READY !\n"); + lpParms->dwReturn = TRUE; + break; + case MCI_STATUS_TIME_FORMAT: + printf("WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n"); + lpParms->dwReturn = MCI_FORMAT_MILLISECONDS; + break; + case MCI_WAVE_INPUT: + printf("WAVE_mciStatus // MCI_WAVE_INPUT !\n"); + lpParms->dwReturn = 0; + break; + case MCI_WAVE_OUTPUT: + printf("WAVE_mciStatus // MCI_WAVE_OUTPUT !\n"); + lpParms->dwReturn = 0; + break; + case MCI_WAVE_STATUS_AVGBYTESPERSEC: + printf("WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n"); + lpParms->dwReturn = 22050; + break; + case MCI_WAVE_STATUS_BITSPERSAMPLE: + printf("WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n"); + lpParms->dwReturn = 8; + break; + case MCI_WAVE_STATUS_BLOCKALIGN: + printf("WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n"); + lpParms->dwReturn = 1; + break; + case MCI_WAVE_STATUS_CHANNELS: + printf("WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n"); + lpParms->dwReturn = 1; + break; + case MCI_WAVE_STATUS_FORMATTAG: + printf("WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n"); + lpParms->dwReturn = WAVE_FORMAT_PCM; + break; + case MCI_WAVE_STATUS_LEVEL: + printf("WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n"); + lpParms->dwReturn = 0xAAAA5555; + break; + case MCI_WAVE_STATUS_SAMPLESPERSEC: + printf("WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n"); + lpParms->dwReturn = 22050; + break; + default: + printf("WAVE_mciStatus // unknowm command %04X !\n", lpParms->dwItem); + return MCIERR_UNRECOGNIZED_COMMAND; + } + } + if (dwFlags & MCI_NOTIFY) { + printf("WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + +/************************************************************************** +* WAVE_mciGetDevCaps [internal] +*/ +DWORD WAVE_mciGetDevCaps(UINT wDevID, DWORD dwFlags, + LPMCI_GETDEVCAPS_PARMS lpParms) +{ + printf("WAVE_mciGetDevCaps(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); + if (lpParms == NULL) return MCIERR_INTERNAL; + if (dwFlags & MCI_GETDEVCAPS_ITEM) { + switch(lpParms->dwItem) { + case MCI_GETDEVCAPS_CAN_RECORD: + lpParms->dwReturn = TRUE; + break; + case MCI_GETDEVCAPS_HAS_AUDIO: + lpParms->dwReturn = TRUE; + break; + case MCI_GETDEVCAPS_HAS_VIDEO: + lpParms->dwReturn = FALSE; + break; + case MCI_GETDEVCAPS_DEVICE_TYPE: + lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO; + break; + case MCI_GETDEVCAPS_USES_FILES: + lpParms->dwReturn = TRUE; + break; + case MCI_GETDEVCAPS_COMPOUND_DEVICE: + lpParms->dwReturn = TRUE; + break; + case MCI_GETDEVCAPS_CAN_EJECT: + lpParms->dwReturn = FALSE; + break; + case MCI_GETDEVCAPS_CAN_PLAY: + lpParms->dwReturn = TRUE; + break; + case MCI_GETDEVCAPS_CAN_SAVE: + lpParms->dwReturn = FALSE; + break; + case MCI_WAVE_GETDEVCAPS_INPUTS: + lpParms->dwReturn = 1; + break; + case MCI_WAVE_GETDEVCAPS_OUTPUTS: + lpParms->dwReturn = 1; + break; + default: + return MCIERR_UNRECOGNIZED_COMMAND; + } + } + return 0; +} + +/************************************************************************** +* WAVE_mciInfo [internal] +*/ +DWORD WAVE_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms) +{ + printf("WAVE_mciInfo(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); + if (lpParms == NULL) return MCIERR_INTERNAL; + lpParms->lpstrReturn = NULL; + switch(dwFlags) { + case MCI_INFO_PRODUCT: + lpParms->lpstrReturn = "Linux Sound System 0.5"; + break; + case MCI_INFO_FILE: + lpParms->lpstrReturn = "FileName"; + break; + case MCI_WAVE_INPUT: + lpParms->lpstrReturn = "Linux Sound System 0.5"; + break; + case MCI_WAVE_OUTPUT: + lpParms->lpstrReturn = "Linux Sound System 0.5"; + break; + default: + return MCIERR_UNRECOGNIZED_COMMAND; + } + if (lpParms->lpstrReturn != NULL) + lpParms->dwRetSize = strlen(lpParms->lpstrReturn); + else + lpParms->dwRetSize = 0; + return 0; +} + + +/*-----------------------------------------------------------------------*/ + + +/************************************************************************** +* wodGetDevCaps [internal] +*/ +DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize) +{ + int audio; + int smplrate; + int samplesize = 16; + int dsp_stereo = 1; + int bytespersmpl; + printf("wodGetDevCaps(%u, %08X, %u);\n", wDevID, lpCaps, dwSize); + if (lpCaps == NULL) return MMSYSERR_NOTENABLED; + audio = open (SOUND_DEV, O_WRONLY, 0); + if (audio == -1) return MMSYSERR_NOTENABLED; + lpCaps->wMid = 0xFF; /* Manufac ID */ + lpCaps->wPid = 0x01; /* Product ID */ + strcpy(lpCaps->szPname, "Linux WAV Driver"); + lpCaps->dwFormats = 0; + lpCaps->dwSupport = 0; + lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2; + bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2; + smplrate = 44100; + if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) { + lpCaps->dwFormats |= WAVE_FORMAT_4M08; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08; + if (bytespersmpl > 1) { + lpCaps->dwFormats |= WAVE_FORMAT_4M16; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16; + } + } + smplrate = 22050; + if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) { + lpCaps->dwFormats |= WAVE_FORMAT_2M08; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08; + if (bytespersmpl > 1) { + lpCaps->dwFormats |= WAVE_FORMAT_2M16; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16; + } + } + smplrate = 11025; + if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) { + lpCaps->dwFormats |= WAVE_FORMAT_1M08; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08; + if (bytespersmpl > 1) { + lpCaps->dwFormats |= WAVE_FORMAT_1M16; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16; + } + } + close(audio); + printf("wodGetDevCaps // dwFormats = %08X\n", lpCaps->dwFormats); + return MMSYSERR_NOERROR; +} + + +/************************************************************************** +* wodOpen [internal] +*/ +DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) +{ + int audio; + int abuf_size; + int smplrate; + int samplesize; + int dsp_stereo; + printf("wodOpen(%u, %08X, %08X);\n", wDevID, lpDesc, dwFlags); + if (lpDesc == NULL) { + printf("Linux 'wodOpen' // Invalid Parameter !\n"); + return MMSYSERR_INVALPARAM; + } + if (wDevID >= MAX_WAVOUTDRV) { + printf("Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n"); + return MMSYSERR_ALLOCATED; + } + WOutDev[wDevID].unixdev = 0; + audio = open (SOUND_DEV, O_WRONLY, 0); + if (audio == -1) { + printf("Linux 'wodOpen' // can't open !\n"); + return MMSYSERR_NOTENABLED; + } + IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size); + if (abuf_size < 4096 || abuf_size > 65536) { + if (abuf_size == -1) + printf("Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n"); + else + printf("Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n"); + return MMSYSERR_NOTENABLED; + } + WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK); + switch(WOutDev[wDevID].wFlags) { + case DCB_NULL: + printf("Linux 'wodOpen' // CALLBACK_NULL !\n"); + break; + case DCB_WINDOW: + printf("Linux 'wodOpen' // CALLBACK_WINDOW !\n"); + break; + case DCB_TASK: + printf("Linux 'wodOpen' // CALLBACK_TASK !\n"); + break; + case DCB_FUNCTION: + printf("Linux 'wodOpen' // CALLBACK_FUNCTION !\n"); + break; + } + WOutDev[wDevID].lpQueueHdr = NULL; + WOutDev[wDevID].unixdev = audio; + WOutDev[wDevID].dwTotalPlayed = 0; + WOutDev[wDevID].bufsize = abuf_size; + memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC)); + if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM) { + printf("Linux 'wodOpen' // Bad format %04X !\n", + lpDesc->lpFormat->wFormatTag); + return WAVERR_BADFORMAT; + } + memcpy(&WOutDev[wDevID].Format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT)); + if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT; + if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT; + if (WOutDev[wDevID].Format.wBitsPerSample == 0) { + WOutDev[wDevID].Format.wBitsPerSample = 8 * + (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / + WOutDev[wDevID].Format.wf.nSamplesPerSec) / + WOutDev[wDevID].Format.wf.nChannels; + } + samplesize = WOutDev[wDevID].Format.wBitsPerSample; + smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec; + dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE; + IOCTL(audio, SNDCTL_DSP_SPEED, smplrate); + IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize); + IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo); + printf("Linux 'wodOpen' // wBitsPerSample=%u !\n", + WOutDev[wDevID].Format.wBitsPerSample); + printf("Linux 'wodOpen' // nSamplesPerSec=%u !\n", + WOutDev[wDevID].Format.wf.nSamplesPerSec); + printf("Linux 'wodOpen' // nChannels=%u !\n", + WOutDev[wDevID].Format.wf.nChannels); + if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) { + printf("Linux 'wodOpen' // can't notify client !\n"); + return MMSYSERR_INVALPARAM; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* wodClose [internal] +*/ +DWORD wodClose(WORD wDevID) +{ + printf("wodClose(%u);\n", wDevID); + if (WOutDev[wDevID].unixdev == 0) { + printf("Linux 'wodClose' // can't close !\n"); + return MMSYSERR_NOTENABLED; + } + close(WOutDev[wDevID].unixdev); + WOutDev[wDevID].unixdev = 0; + WOutDev[wDevID].bufsize = 0; + if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) { + printf("Linux 'wodClose' // can't notify client !\n"); + return MMSYSERR_INVALPARAM; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* wodWrite [internal] +*/ +DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize) +{ + printf("wodWrite(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize); + if (WOutDev[wDevID].unixdev == 0) { + printf("Linux 'wodWrite' // can't play !\n"); + return MMSYSERR_NOTENABLED; + } + if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED; + if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED; + if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING; + lpWaveHdr->dwFlags &= ~WHDR_DONE; + lpWaveHdr->dwFlags |= WHDR_INQUEUE; + printf("wodWrite() // dwBytesRecorded %u !\n", lpWaveHdr->dwBytesRecorded); + if (write (WOutDev[wDevID].unixdev, lpWaveHdr->lpData, + lpWaveHdr->dwBytesRecorded) != lpWaveHdr->dwBytesRecorded) { + return MMSYSERR_NOTENABLED; + } + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE; + lpWaveHdr->dwFlags |= WHDR_DONE; + if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) { + printf("Linux 'wodWrite' // can't notify client !\n"); + return MMSYSERR_INVALPARAM; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* wodPrepare [internal] +*/ +DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize) +{ + printf("wodPrepare(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize); + if (WOutDev[wDevID].unixdev == 0) { + printf("Linux 'wodPrepare' // can't prepare !\n"); + return MMSYSERR_NOTENABLED; + } + if (WOutDev[wDevID].lpQueueHdr != NULL) { + printf("Linux 'wodPrepare' // already prepare !\n"); + return MMSYSERR_NOTENABLED; + } + WOutDev[wDevID].dwTotalPlayed = 0; + WOutDev[wDevID].lpQueueHdr = lpWaveHdr; + if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING; + lpWaveHdr->dwFlags |= WHDR_PREPARED; + lpWaveHdr->dwFlags &= ~WHDR_DONE; + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* wodUnprepare [internal] +*/ +DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize) +{ + printf("wodUnprepare(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize); + if (WOutDev[wDevID].unixdev == 0) { + printf("Linux 'wodUnprepare' // can't unprepare !\n"); + return MMSYSERR_NOTENABLED; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* wodRestart [internal] +*/ +DWORD wodRestart(WORD wDevID) +{ + printf("wodRestart(%u);\n", wDevID); + if (WOutDev[wDevID].unixdev == 0) { + printf("Linux 'wodRestart' // can't restart !\n"); + return MMSYSERR_NOTENABLED; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* wodReset [internal] +*/ +DWORD wodReset(WORD wDevID) +{ + printf("wodReset(%u);\n", wDevID); + if (WOutDev[wDevID].unixdev == 0) { + printf("Linux 'wodReset' // can't reset !\n"); + return MMSYSERR_NOTENABLED; + } + return MMSYSERR_NOERROR; +} + + +/************************************************************************** +* wodGetPosition [internal] +*/ +DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) +{ + int time; + printf("wodGetPosition(%u, %08X, %u);\n", wDevID, lpTime, uSize); + if (WOutDev[wDevID].unixdev == 0) { + printf("Linux 'wodGetPosition' // can't get pos !\n"); + return MMSYSERR_NOTENABLED; + } + if (lpTime == NULL) return MMSYSERR_INVALPARAM; +TryAGAIN: + switch(lpTime->wType) { + case TIME_BYTES: + lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed; + printf("wodGetPosition // TIME_BYTES=%u\n", lpTime->u.cb); + break; + case TIME_SAMPLES: + lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 / + WOutDev[wDevID].Format.wBitsPerSample; + printf("wodGetPosition // TIME_SAMPLES=%u\n", lpTime->u.sample); + break; + case TIME_MS: + lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed / + (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000); + printf("wodGetPosition // TIME_MS=%u\n", lpTime->u.ms); + break; + case TIME_SMPTE: + time = WOutDev[wDevID].dwTotalPlayed / + (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000); + lpTime->u.smpte.hour = time / 108000; + time -= lpTime->u.smpte.hour * 108000; + lpTime->u.smpte.min = time / 1800; + time -= lpTime->u.smpte.min * 1800; + lpTime->u.smpte.sec = time / 30; + time -= lpTime->u.smpte.sec * 30; + lpTime->u.smpte.frame = time; + lpTime->u.smpte.fps = 30; + printf("wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n", + lpTime->u.smpte.hour, lpTime->u.smpte.min, + lpTime->u.smpte.sec, lpTime->u.smpte.frame); + break; + default: + printf("wodGetPosition() format not supported ! use TIME_MS !\n"); + lpTime->wType = TIME_MS; + goto TryAGAIN; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* wodSetVolume [internal] +*/ +DWORD wodSetVolume(WORD wDevID, DWORD dwParam) +{ + int mixer; + int volume = 50; + printf("wodSetVolume(%u, %08X);\n", wDevID, dwParam); + if (WOutDev[wDevID].unixdev == 0) { + printf("Linux 'wodSetVolume' // can't set volume !\n"); + return MMSYSERR_NOTENABLED; + } + if ((mixer = open("/dev/mixer", O_RDWR)) < 0) { + printf("Linux 'wodSetVolume' // mixer device not available !\n"); + return MMSYSERR_NOTENABLED; + } + if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) { + printf("Linux 'wodSetVolume' // unable set mixer !\n"); + return MMSYSERR_NOTENABLED; + } + close(mixer); + return MMSYSERR_NOERROR; +} + + /************************************************************************** * wodMessage [sample driver] */ DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { + printf("wodMessage(%u, %04X, %08X, %08X, %08X);\n", + wDevID, wMsg, dwUser, dwParam1, dwParam2); + switch(wMsg) { + case WODM_OPEN: + return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2); + case WODM_CLOSE: + return wodClose(wDevID); + case WODM_WRITE: + return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2); + case WODM_PAUSE: + return 0L; + case WODM_GETPOS: + return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2); + case WODM_BREAKLOOP: + return 0L; + case WODM_PREPARE: + return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2); + case WODM_UNPREPARE: + return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2); + case WODM_GETDEVCAPS: + return wodGetDevCaps(wDevID, (LPWAVEOUTCAPS)dwParam1, dwParam2); + case WODM_GETNUMDEVS: + return 1L; + case WODM_GETPITCH: + return 0L; + case WODM_SETPITCH: + return 0L; + case WODM_GETPLAYBACKRATE: + return 0L; + case WODM_SETPLAYBACKRATE: + return 0L; + case WODM_GETVOLUME: + return 0L; + case WODM_SETVOLUME: + return wodSetVolume(wDevID, dwParam1); + case WODM_RESTART: + return wodRestart(wDevID); + case WODM_RESET: + return wodReset(wDevID); + } + return MMSYSERR_NOTSUPPORTED; +} + + +/*-----------------------------------------------------------------------*/ + +/************************************************************************** +* widGetDevCaps [internal] +*/ +DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS lpCaps, DWORD dwSize) +{ + int audio; + int smplrate; + int samplesize = 16; + int dsp_stereo = 1; + int bytespersmpl; + printf("widGetDevCaps(%u, %08X, %u);\n", wDevID, lpCaps, dwSize); + if (lpCaps == NULL) return MMSYSERR_NOTENABLED; + audio = open (SOUND_DEV, O_RDONLY, 0); + if (audio == -1) return MMSYSERR_NOTENABLED; + lpCaps->wMid = 0xFF; /* Manufac ID */ + lpCaps->wPid = 0x01; /* Product ID */ + strcpy(lpCaps->szPname, "Linux WAV Driver"); + lpCaps->dwFormats = 0; + lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2; + bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2; + smplrate = 44100; + if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) { + lpCaps->dwFormats |= WAVE_FORMAT_4M08; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08; + if (bytespersmpl > 1) { + lpCaps->dwFormats |= WAVE_FORMAT_4M16; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16; + } + } + smplrate = 22050; + if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) { + lpCaps->dwFormats |= WAVE_FORMAT_2M08; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08; + if (bytespersmpl > 1) { + lpCaps->dwFormats |= WAVE_FORMAT_2M16; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16; + } + } + smplrate = 11025; + if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) { + lpCaps->dwFormats |= WAVE_FORMAT_1M08; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08; + if (bytespersmpl > 1) { + lpCaps->dwFormats |= WAVE_FORMAT_1M16; + if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16; + } + } + close(audio); + printf("widGetDevCaps // dwFormats = %08X\n", lpCaps->dwFormats); + return MMSYSERR_NOERROR; +} + + +/************************************************************************** +* widOpen [internal] +*/ +DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags) +{ + int audio; + int abuf_size; + int smplrate; + int samplesize; + int dsp_stereo; + printf("widOpen(%u, %08X, %08X);\n", wDevID, lpDesc, dwFlags); + if (lpDesc == NULL) { + printf("Linux 'widOpen' // Invalid Parameter !\n"); + return MMSYSERR_INVALPARAM; + } + if (wDevID >= MAX_WAVINDRV) { + printf("Linux 'widOpen' // MAX_WAVINDRV reached !\n"); + return MMSYSERR_ALLOCATED; + } + WInDev[wDevID].unixdev = 0; + audio = open (SOUND_DEV, O_RDONLY, 0); + if (audio == -1) { + printf("Linux 'widOpen' // can't open !\n"); + return MMSYSERR_NOTENABLED; + } + IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size); + if (abuf_size < 4096 || abuf_size > 65536) { + if (abuf_size == -1) + printf("Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n"); + else + printf("Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n"); + return MMSYSERR_NOTENABLED; + } + WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK); + switch(WInDev[wDevID].wFlags) { + case DCB_NULL: + printf("Linux 'widOpen' // CALLBACK_NULL !\n"); + break; + case DCB_WINDOW: + printf("Linux 'widOpen' // CALLBACK_WINDOW !\n"); + break; + case DCB_TASK: + printf("Linux 'widOpen' // CALLBACK_TASK !\n"); + break; + case DCB_FUNCTION: + printf("Linux 'widOpen' // CALLBACK_FUNCTION !\n"); + break; + } + WInDev[wDevID].lpQueueHdr = NULL; + WInDev[wDevID].unixdev = audio; + WInDev[wDevID].bufsize = abuf_size; + WInDev[wDevID].dwTotalRecorded = 0; + memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC)); + if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM) { + printf("Linux 'widOpen' // Bad format %04X !\n", + lpDesc->lpFormat->wFormatTag); + return WAVERR_BADFORMAT; + } + memcpy(&WInDev[wDevID].Format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT)); + WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */ + if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT; + if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT; + if (WInDev[wDevID].Format.wBitsPerSample == 0) { + WInDev[wDevID].Format.wBitsPerSample = 8 * + (WInDev[wDevID].Format.wf.nAvgBytesPerSec / + WInDev[wDevID].Format.wf.nSamplesPerSec) / + WInDev[wDevID].Format.wf.nChannels; + } + samplesize = WInDev[wDevID].Format.wBitsPerSample; + smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec; + dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE; + IOCTL(audio, SNDCTL_DSP_SPEED, smplrate); + IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize); + IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo); +#ifdef DEBUG_MCIWAVE + printf("Linux 'widOpen' // wBitsPerSample=%u !\n", + WInDev[wDevID].Format.wBitsPerSample); + printf("Linux 'widOpen' // nSamplesPerSec=%u !\n", + WInDev[wDevID].Format.wf.nSamplesPerSec); + printf("Linux 'widOpen' // nChannels=%u !\n", + WInDev[wDevID].Format.wf.nChannels); + printf("Linux 'widOpen' // nAvgBytesPerSec=%u\n", + WInDev[wDevID].Format.wf.nAvgBytesPerSec); +#endif + if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) { + printf("Linux 'widOpen' // can't notify client !\n"); + return MMSYSERR_INVALPARAM; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* widClose [internal] +*/ +DWORD widClose(WORD wDevID) +{ + printf("widClose(%u);\n", wDevID); + if (WInDev[wDevID].unixdev == 0) { + printf("Linux 'widClose' // can't close !\n"); + return MMSYSERR_NOTENABLED; + } + close(WInDev[wDevID].unixdev); + WInDev[wDevID].unixdev = 0; + WInDev[wDevID].bufsize = 0; + if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) { + printf("Linux 'widClose' // can't notify client !\n"); + return MMSYSERR_INVALPARAM; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* widAddBuffer [internal] +*/ +DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize) +{ + int count = 1; + LPWAVEHDR lpWIHdr; + printf("widAddBuffer(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize); + if (WInDev[wDevID].unixdev == 0) { + printf("Linux 'widAddBuffer' // can't do it !\n"); + return MMSYSERR_NOTENABLED; + } + if (WInDev[wDevID].lpQueueHdr == NULL || + !(lpWaveHdr->dwFlags & WHDR_PREPARED)) { + printf("Linux 'widAddBuffer' // never been prepared !\n"); + return WAVERR_UNPREPARED; + } + if ((lpWaveHdr->dwFlags & WHDR_INQUEUE) && + (WInDev[wDevID].lpQueueHdr != lpWaveHdr)) { + /* except if it's the one just prepared ... */ + printf("Linux 'widAddBuffer' // header already in use !\n"); + return WAVERR_STILLPLAYING; + } + lpWaveHdr->dwFlags |= WHDR_PREPARED; + lpWaveHdr->dwFlags |= WHDR_INQUEUE; + lpWaveHdr->dwFlags &= ~WHDR_DONE; + lpWaveHdr->dwBytesRecorded = 0; + /* added to the queue, except if it's the one just prepared ... */ + if (WInDev[wDevID].lpQueueHdr != lpWaveHdr) { + lpWIHdr = WInDev[wDevID].lpQueueHdr; + while (lpWIHdr->lpNext != NULL) { + lpWIHdr = lpWIHdr->lpNext; + count++; + } + lpWIHdr->lpNext = lpWaveHdr; + count++; + } + printf("widAddBuffer // buffer added ! (now %u in queue)\n", count); + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* widPrepare [internal] +*/ +DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize) +{ + printf("widPrepare(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize); + if (WInDev[wDevID].unixdev == 0) { + printf("Linux 'widPrepare' // can't prepare !\n"); + return MMSYSERR_NOTENABLED; + } + if (WInDev[wDevID].lpQueueHdr != NULL) { + printf("Linux 'widPrepare' // already prepare !\n"); + return WAVERR_BADFORMAT; + } + WInDev[wDevID].dwTotalRecorded = 0; + WInDev[wDevID].lpQueueHdr = lpWaveHdr; + if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING; + lpWaveHdr->dwFlags |= WHDR_PREPARED; + lpWaveHdr->dwFlags |= WHDR_INQUEUE; + lpWaveHdr->dwFlags &= ~WHDR_DONE; + lpWaveHdr->dwBytesRecorded = 0; + printf("Linux 'widPrepare' // header prepared !\n"); + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* widUnprepare [internal] +*/ +DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize) +{ + printf("widUnprepare(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize); + if (WInDev[wDevID].unixdev == 0) { + printf("Linux 'widUnprepare' // can't unprepare !\n"); + return MMSYSERR_NOTENABLED; + } + lpWaveHdr->dwFlags &= ~WHDR_PREPARED; + lpWaveHdr->dwFlags &= ~WHDR_INQUEUE; + lpWaveHdr->dwFlags |= WHDR_DONE; + WInDev[wDevID].lpQueueHdr = NULL; + printf("Linux 'widUnprepare' // all headers unprepared !\n"); + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* widStart [internal] +*/ +DWORD widStart(WORD wDevID) +{ + int count = 1; + LPWAVEHDR lpWIHdr; + printf("widStart(%u);\n", wDevID); + if (WInDev[wDevID].unixdev == 0) { + printf("Linux 'widStart' // can't start recording !\n"); + return MMSYSERR_NOTENABLED; + } + if (WInDev[wDevID].lpQueueHdr == NULL || + WInDev[wDevID].lpQueueHdr->lpData == NULL) { + printf("Linux 'widStart' // never been prepared !\n"); + return WAVERR_UNPREPARED; + } + lpWIHdr = WInDev[wDevID].lpQueueHdr; + while(lpWIHdr != NULL) { + lpWIHdr->dwBufferLength &= 0xFFFF; + printf("widStart // recording buf#%u=%08X size=%u \n", + count, lpWIHdr->lpData, lpWIHdr->dwBufferLength); + fflush(stdout); + read (WInDev[wDevID].unixdev, lpWIHdr->lpData, + lpWIHdr->dwBufferLength); + lpWIHdr->dwBytesRecorded = lpWIHdr->dwBufferLength; + WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded; + lpWIHdr->dwFlags &= ~WHDR_INQUEUE; + lpWIHdr->dwFlags |= WHDR_DONE; + if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWIHdr, 0L) != + MMSYSERR_NOERROR) { + printf("Linux 'widStart' // can't notify client !\n"); + return MMSYSERR_INVALPARAM; + } + lpWIHdr = lpWIHdr->lpNext; + count++; + } + printf("widStart // end of recording !\n"); + fflush(stdout); + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* widStop [internal] +*/ +DWORD widStop(WORD wDevID) +{ + printf("widStop(%u);\n", wDevID); + if (WInDev[wDevID].unixdev == 0) { + printf("Linux 'widStop' // can't stop !\n"); + return MMSYSERR_NOTENABLED; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* widReset [internal] +*/ +DWORD widReset(WORD wDevID) +{ + printf("widReset(%u);\n", wDevID); + if (WInDev[wDevID].unixdev == 0) { + printf("Linux 'widReset' // can't reset !\n"); + return MMSYSERR_NOTENABLED; + } + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* widGetPosition [internal] +*/ +DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize) +{ + int time; +#ifdef DEBUG_MCIWAVE + printf("widGetPosition(%u, %08X, %u);\n", wDevID, lpTime, uSize); +#endif + if (WInDev[wDevID].unixdev == 0) { + printf("Linux 'widGetPosition' // can't get pos !\n"); + return MMSYSERR_NOTENABLED; + } + if (lpTime == NULL) return MMSYSERR_INVALPARAM; +TryAGAIN: +#ifdef DEBUG_MCIWAVE + printf("widGetPosition // wType=%04X !\n", lpTime->wType); + printf("widGetPosition // wBitsPerSample=%u\n", + WInDev[wDevID].Format.wBitsPerSample); + printf("widGetPosition // nSamplesPerSec=%u\n", + WInDev[wDevID].Format.wf.nSamplesPerSec); + printf("widGetPosition // nChannels=%u\n", + WInDev[wDevID].Format.wf.nChannels); + printf("widGetPosition // nAvgBytesPerSec=%u\n", + WInDev[wDevID].Format.wf.nAvgBytesPerSec); + fflush(stdout); +#endif + switch(lpTime->wType) { + case TIME_BYTES: + lpTime->u.cb = WInDev[wDevID].dwTotalRecorded; + printf("widGetPosition // TIME_BYTES=%u\n", lpTime->u.cb); + break; + case TIME_SAMPLES: + lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 / + WInDev[wDevID].Format.wBitsPerSample; + printf("widGetPosition // TIME_SAMPLES=%u\n", lpTime->u.sample); + break; + case TIME_MS: + lpTime->u.ms = WInDev[wDevID].dwTotalRecorded / + (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000); + printf("widGetPosition // TIME_MS=%u\n", lpTime->u.ms); + break; + case TIME_SMPTE: + time = WInDev[wDevID].dwTotalRecorded / + (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000); + lpTime->u.smpte.hour = time / 108000; + time -= lpTime->u.smpte.hour * 108000; + lpTime->u.smpte.min = time / 1800; + time -= lpTime->u.smpte.min * 1800; + lpTime->u.smpte.sec = time / 30; + time -= lpTime->u.smpte.sec * 30; + lpTime->u.smpte.frame = time; + lpTime->u.smpte.fps = 30; + printf("widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n", + lpTime->u.smpte.hour, lpTime->u.smpte.min, + lpTime->u.smpte.sec, lpTime->u.smpte.frame); + break; + default: + printf("widGetPosition() format not supported ! use TIME_MS !\n"); + lpTime->wType = TIME_MS; + goto TryAGAIN; + } + return MMSYSERR_NOERROR; } /************************************************************************** @@ -62,15 +1454,39 @@ DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { + printf("widMessage(%u, %04X, %08X, %08X, %08X);\n", + wDevID, wMsg, dwUser, dwParam1, dwParam2); + switch(wMsg) { + case WIDM_OPEN: + return widOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2); + case WIDM_CLOSE: + return widClose(wDevID); + case WIDM_ADDBUFFER: + return widAddBuffer(wDevID, (LPWAVEHDR)dwParam1, dwParam2); + case WIDM_PREPARE: + return widPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2); + case WIDM_UNPREPARE: + return widUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2); + case WIDM_GETDEVCAPS: + return widGetDevCaps(wDevID, (LPWAVEINCAPS)dwParam1, dwParam2); + case WIDM_GETNUMDEVS: + return 1L; + case WIDM_GETPOS: + return widGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2); + case WIDM_RESET: + return widReset(wDevID); + case WIDM_START: + return widStart(wDevID); + case WIDM_STOP: + return widStop(wDevID); + } + return MMSYSERR_NOTSUPPORTED; } -/************************************************************************** -* auxMessage [sample driver] -*/ -DWORD auxMessage(WORD wDevID, WORD wMsg, DWORD dwUser, - DWORD dwParam1, DWORD dwParam2) -{ -} + +/*-----------------------------------------------------------------------*/ + + /************************************************************************** * midMessage [sample driver] @@ -78,6 +1494,7 @@ DWORD auxMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD midMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { + return MMSYSERR_NOTENABLED; } /************************************************************************** @@ -86,12 +1503,7 @@ DWORD midMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD modMessage(WORD wDevID, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { + return MMSYSERR_NOTENABLED; } -/* -BOOL DriverCallback(DWORD dwCallBack, UINT uFlags, HANDLE hDev, - WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2); -*/ - - diff --git a/misc/comm.c b/misc/comm.c index 8f7f9bc3ed9..4c6edfb67bb 100644 --- a/misc/comm.c +++ b/misc/comm.c @@ -18,21 +18,12 @@ #include "wine.h" #include "windows.h" +#include "comm.h" /* #define DEBUG_COMM /* */ -#define MAX_PORTS 16 - int commerror = 0, eventmask = 0; -struct DosDeviceStruct { - char *devicename; /* /dev/cua1 */ - int fd; - int suspended; - int unget; - int unget_byte; -}; - struct DosDeviceStruct COM[MAX_PORTS]; struct DosDeviceStruct LPT[MAX_PORTS]; diff --git a/misc/dos_fs.c b/misc/dos_fs.c index dc3b1bb63ac..bb1d3e58f7c 100644 --- a/misc/dos_fs.c +++ b/misc/dos_fs.c @@ -27,6 +27,7 @@ #include "msdos.h" #include "prototypes.h" #include "autoconf.h" +#include "comm.h" /* #define DEBUG /* */ @@ -170,6 +171,11 @@ WORD DOS_GetEquipment(void) { WORD equipment; int diskdrives = 0; + int parallelports = 0; + int serialports = 0; + int x; + extern struct DosDeviceStruct COM[MAX_PORTS]; + extern struct DosDeviceStruct LPT[MAX_PORTS]; /* borrowed from Ralph Brown's interrupt lists @@ -190,6 +196,12 @@ WORD DOS_GetEquipment(void) bit 1: =1 if math co-processor bit 0: =1 if diskette available for boot */ +/* Currently the only of these bits correctly set are: + bits 15-14 } Added by William Owen Smith, + bits 11-9 } wos@dcs.warwick.ac.uk + bits 7-6 + bit 2 (always set) +*/ if (DosDrives[0].rootdir != NULL) diskdrives++; @@ -197,8 +209,27 @@ WORD DOS_GetEquipment(void) diskdrives++; if (diskdrives) diskdrives--; + + for (x=0; x!=MAX_PORTS; x++) { + if (COM[x].devicename) + serialports++; + if (LPT[x].devicename) + parallelports++; + } + if (serialports > 7) /* 3 bits -- maximum value = 7 */ + serialports=7; + if (parallelports > 3) /* 2 bits -- maximum value = 3 */ + parallelports=3; - equipment = (diskdrives << 6) || 0x02; + equipment = (diskdrives << 6) | (serialports << 9) | + (parallelports << 14) | 0x02; + +#ifdef DEBUG + fprintf(stderr, "DOS_GetEquipment : diskdrives = %d serialports = %d " + "parallelports = %d\n" + "DOS_GetEquipment : equipment = %d\n", + diskdrives, serialports, parallelports, equipment); +#endif return (equipment); } diff --git a/misc/file.c b/misc/file.c index e5d72713ce0..29ed1734b11 100644 --- a/misc/file.c +++ b/misc/file.c @@ -61,7 +61,7 @@ INT _lopen (LPSTR lpPathName, INT iReadWrite) /*************************************************************************** _lread ***************************************************************************/ -INT _lread (INT hFile, LPSTR lpBuffer, INT wBytes) +INT _lread (INT hFile, LPSTR lpBuffer, WORD wBytes) { int result; @@ -81,7 +81,7 @@ INT _lread (INT hFile, LPSTR lpBuffer, INT wBytes) /**************************************************************************** _lwrite ****************************************************************************/ -INT _lwrite (INT hFile, LPSTR lpBuffer, INT wBytes) +INT _lwrite (INT hFile, LPSTR lpBuffer, WORD wBytes) { int result; diff --git a/misc/main.c b/misc/main.c index f238568d376..4e94a7af505 100644 --- a/misc/main.c +++ b/misc/main.c @@ -53,7 +53,6 @@ struct options Options = FALSE, /* usePrivateMap */ FALSE, /* synchronous */ FALSE, /* no backing store */ - FALSE, /* no save unders */ SW_SHOWNORMAL, /* cmdShow */ FALSE }; @@ -69,7 +68,6 @@ static XrmOptionDescRec optionsTable[] = { "-privatemap", ".privatemap", XrmoptionNoArg, (caddr_t)"on" }, { "-synchronous", ".synchronous", XrmoptionNoArg, (caddr_t)"on" }, { "-nobackingstore",".nobackingstore", XrmoptionNoArg, (caddr_t)"on" }, - { "-nosaveunders", ".nosaveunders", XrmoptionNoArg, (caddr_t)"on" }, { "-spy", ".spy", XrmoptionSepArg, (caddr_t)NULL }, { "-debug", ".debug", XrmoptionNoArg, (caddr_t)"on" }, { "-relaydbg", ".relaydbg", XrmoptionNoArg, (caddr_t)"on" } @@ -90,7 +88,6 @@ static XrmOptionDescRec optionsTable[] = " -privatemap Use a private color map\n" \ " -synchronous Turn on synchronous display mode\n" \ " -nobackingstore Turn off backing store\n" \ - " -nosaveunders Turn off saveunders\n" \ " -spy file Turn on message spying to the specified file\n" \ " -relaydbg Display call relay information\n" @@ -245,8 +242,6 @@ static void MAIN_ParseOptions( int *argc, char *argv[] ) Options.usePrivateMap = TRUE; if (MAIN_GetResource( db, ".synchronous", &value )) Options.synchronous = TRUE; - if (MAIN_GetResource( db, ".nosaveunders", &value )) - Options.nosaveunders = TRUE; if (MAIN_GetResource( db, ".nobackingstore", &value )) Options.nobackingstore = TRUE; if (MAIN_GetResource( db, ".relaydbg", &value )) @@ -297,16 +292,11 @@ static void MAIN_CreateDesktop( int argc, char *argv[] ) else win_attr.backing_store = Always; - if (Options.nosaveunders) - win_attr.save_under = FALSE; - else - win_attr.save_under = TRUE; - rootWindow = XCreateWindow( display, DefaultRootWindow(display), desktopX, desktopY, width, height, 0, CopyFromParent, InputOutput, CopyFromParent, - CWEventMask | CWCursor | CWSaveUnder | - CWBackingStore, &win_attr ); + CWEventMask | CWCursor | + CWBackingStore, &win_attr ); /* Set window manager properties */ diff --git a/misc/mcicda.c b/misc/mcicda.c new file mode 100644 index 00000000000..55497be5335 --- /dev/null +++ b/misc/mcicda.c @@ -0,0 +1,859 @@ +/* + * Sample MCI CDAUDIO Wine Driver for Linux + * + * Copyright 1994 Martin Ayotte + */ + +static char Copyright[] = "Copyright Martin Ayotte, 1994"; + +/* +#define DEBUG_CDAUDIO +*/ + +#include "stdio.h" +#include "win.h" +#include "user.h" +#include "driver.h" +#include "mmsystem.h" + +#include +#include +#include +#include + +#define SOUND_DEV "/dev/dsp" +#define CDAUDIO_DEV "/dev/sbpcd" + +#ifdef SOUND_VERSION +#define IOCTL(a,b,c) ioctl(a,b,&c) +#else +#define IOCTL(a,b,c) (c = ioctl(a,b,c) ) +#endif + +#define MAX_CDAUDIODRV 2 +#define MAX_CDAUDIO_TRACKS 256 + +#define CDFRAMES_PERSEC 75 +#define CDFRAMES_PERMIN 4500 +#define SECONDS_PERMIN 60 + +typedef struct { + int nUseCount; /* Incremented for each shared open */ + BOOL fShareable; /* TRUE if first open was shareable */ + WORD wNotifyDeviceID; /* MCI device ID with a pending notification */ + HANDLE hCallback; /* Callback handle for pending notification */ + MCI_OPEN_PARMS openParms; + DWORD dwTimeFormat; + int unixdev; + struct cdrom_subchnl sc; + int mode; + UINT nCurTrack; + DWORD dwCurFrame; + UINT nTracks; + DWORD dwTotalLen; + LPDWORD lpdwTrackLen; + LPDWORD lpdwTrackPos; + DWORD dwFirstOffset; + } LINUX_CDAUDIO; + +static LINUX_CDAUDIO CDADev[MAX_CDAUDIODRV]; + +UINT CDAUDIO_GetNumberOfTracks(UINT wDevID); +BOOL CDAUDIO_GetTracksInfo(UINT wDevID); +BOOL CDAUDIO_GetCDStatus(UINT wDevID); +DWORD CDAUDIO_CalcTime(UINT wDevID, DWORD dwFormatType, DWORD dwFrame); + + +/*-----------------------------------------------------------------------*/ + + +/************************************************************************** +* CDAUDIO_mciOpen [internal] +*/ +DWORD CDAUDIO_mciOpen(DWORD dwFlags, LPMCI_OPEN_PARMS lpParms) +{ + UINT wDevID; + int cdrom; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciOpen(%08X, %08X);\n", dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + wDevID = lpParms->wDeviceID; + if (CDADev[wDevID].nUseCount > 0) { + /* The driver already open on this channel */ + /* If the driver was% op, ened shareable before and this open specifies */ + /* shareable then increment the use count */ + if (CDADev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE)) + ++CDADev[wDevID].nUseCount; + else + return MCIERR_MUST_USE_SHAREABLE; + } + else { + CDADev[wDevID].nUseCount = 1; + CDADev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE; + } + if (dwFlags & MCI_OPEN_ELEMENT) { + printf("CDAUDIO_mciOpen // MCI_OPEN_ELEMENT !\n"); +/* return MCIERR_NO_ELEMENT_ALLOWED; */ + } + memcpy(&CDADev[wDevID].openParms, lpParms, sizeof(MCI_OPEN_PARMS)); + CDADev[wDevID].wNotifyDeviceID = lpParms->wDeviceID; + CDADev[wDevID].unixdev = open (CDAUDIO_DEV, O_RDONLY, 0); + if (CDADev[wDevID].unixdev == -1) { + printf("CDAUDIO_mciOpen // can't open '%s' !\n", CDAUDIO_DEV); + return MCIERR_HARDWARE; + } + CDADev[wDevID].mode = 0; + CDADev[wDevID].dwTimeFormat = MCI_FORMAT_TMSF; + CDADev[wDevID].nCurTrack = 0; + CDADev[wDevID].nTracks = 0; + CDADev[wDevID].dwTotalLen = 0; + CDADev[wDevID].dwFirstOffset = 0; + CDADev[wDevID].lpdwTrackLen = NULL; + CDADev[wDevID].lpdwTrackPos = NULL; + if (!CDAUDIO_GetTracksInfo(wDevID)) { + printf("CDAUDIO_mciOpen // error reading TracksInfo !\n"); +/* return MCIERR_INTERNAL; */ + } + if (dwFlags & MCI_NOTIFY) { + printf("CDAUDIO_mciOpen // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + +/************************************************************************** +* CDAUDIO_mciClose [internal] +*/ +DWORD CDAUDIO_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms) +{ +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciClose(%u, %08X, %08X);\n", wDevID, dwParam, lpParms); +#endif + if (CDADev[wDevID].lpdwTrackLen != NULL) free(CDADev[wDevID].lpdwTrackLen); + if (CDADev[wDevID].lpdwTrackPos != NULL) free(CDADev[wDevID].lpdwTrackPos); + close(CDADev[wDevID].unixdev); +} + +/************************************************************************** +* CDAUDIO_mciGetDevCaps [internal] +*/ +DWORD CDAUDIO_mciGetDevCaps(UINT wDevID, DWORD dwFlags, + LPMCI_GETDEVCAPS_PARMS lpParms) +{ +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciGetDevCaps(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + if (dwFlags & MCI_GETDEVCAPS_ITEM) { + printf("CDAUDIO_mciGetDevCaps // MCI_GETDEVCAPS_ITEM dwItem=%08X);\n", + lpParms->dwItem); + switch(lpParms->dwItem) { + case MCI_GETDEVCAPS_CAN_RECORD: + lpParms->dwReturn = FALSE; + break; + case MCI_GETDEVCAPS_HAS_AUDIO: + lpParms->dwReturn = TRUE; + break; + case MCI_GETDEVCAPS_HAS_VIDEO: + lpParms->dwReturn = FALSE; + break; + case MCI_GETDEVCAPS_DEVICE_TYPE: + lpParms->dwReturn = MCI_DEVTYPE_CD_AUDIO; + break; + case MCI_GETDEVCAPS_USES_FILES: + lpParms->dwReturn = FALSE; + break; + case MCI_GETDEVCAPS_COMPOUND_DEVICE: + lpParms->dwReturn = FALSE; + break; + case MCI_GETDEVCAPS_CAN_EJECT: + lpParms->dwReturn = TRUE; + break; + case MCI_GETDEVCAPS_CAN_PLAY: + lpParms->dwReturn = TRUE; + break; + case MCI_GETDEVCAPS_CAN_SAVE: + lpParms->dwReturn = FALSE; + break; + default: + return MCIERR_UNRECOGNIZED_COMMAND; + } + } + printf("CDAUDIO_mciGetDevCaps // lpParms->dwReturn=%08X);\n", lpParms->dwReturn); + return 0; +} + +/************************************************************************** +* CDAUDIO_mciInfo [internal] +*/ +DWORD CDAUDIO_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms) +{ +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciInfo(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + lpParms->lpstrReturn = NULL; + switch(dwFlags) { + case MCI_INFO_PRODUCT: + lpParms->lpstrReturn = "Linux CDROM 0.5"; + break; + default: + return MCIERR_UNRECOGNIZED_COMMAND; + } + if (lpParms->lpstrReturn != NULL) + lpParms->dwRetSize = strlen(lpParms->lpstrReturn); + else + lpParms->dwRetSize = 0; + return 0; +} + +/************************************************************************** +* CDAUDIO_mciStatus [internal] +*/ +DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms) +{ +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciStatus(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + if (CDADev[wDevID].unixdev == 0) return MMSYSERR_NOTENABLED; + if (dwFlags & MCI_NOTIFY) { +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciStatus // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); +#endif + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + if (dwFlags & MCI_STATUS_ITEM) { + switch(lpParms->dwItem) { + case MCI_STATUS_CURRENT_TRACK: + if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL; + lpParms->dwReturn = CDADev[wDevID].nCurTrack; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciStatus // CURRENT_TRACK=%u!\n", lpParms->dwReturn); +#endif + return 0; + case MCI_STATUS_LENGTH: + if (CDADev[wDevID].nTracks == 0) { + if (!CDAUDIO_GetTracksInfo(wDevID)) { + printf("CDAUDIO_mciStatus // error reading TracksInfo !\n"); + return MCIERR_INTERNAL; + } + } + if (dwFlags & MCI_TRACK) { + printf("CDAUDIO_mciStatus // MCI_TRACK #%u LENGTH=??? !\n", + lpParms->dwTrack); + if (lpParms->dwTrack > CDADev[wDevID].nTracks) + return MCIERR_OUTOFRANGE; + lpParms->dwReturn = CDADev[wDevID].lpdwTrackLen[lpParms->dwTrack]; + } + else + lpParms->dwReturn = CDADev[wDevID].dwTotalLen; + lpParms->dwReturn = CDAUDIO_CalcTime(wDevID, + CDADev[wDevID].dwTimeFormat, lpParms->dwReturn); + printf("CDAUDIO_mciStatus // LENGTH=%u !\n", lpParms->dwReturn); + return 0; + case MCI_STATUS_MODE: + if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL; + lpParms->dwReturn = CDADev[wDevID].mode; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciStatus // MCI_STATUS_MODE=%08X !\n", + lpParms->dwReturn); +#endif + return 0; + case MCI_STATUS_MEDIA_PRESENT: + lpParms->dwReturn = (CDADev[wDevID].nTracks > 0) ? TRUE : FALSE; + if (lpParms->dwReturn == FALSE) + printf("CDAUDIO_mciStatus // MEDIA_NOT_PRESENT !\n"); + else + printf("CDAUDIO_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n"); + return 0; + case MCI_STATUS_NUMBER_OF_TRACKS: + lpParms->dwReturn = CDAUDIO_GetNumberOfTracks(wDevID); + printf("CDAUDIO_mciStatus // MCI_STATUS_NUMBER_OF_TRACKS = %u !\n", + lpParms->dwReturn); + if (lpParms->dwReturn == (WORD)-1) return MCIERR_INTERNAL; + return 0; + case MCI_STATUS_POSITION: + if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL; + lpParms->dwReturn = CDADev[wDevID].dwCurFrame; + if (dwFlags & MCI_STATUS_START) { + lpParms->dwReturn = CDADev[wDevID].dwFirstOffset; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciStatus // get MCI_STATUS_START !\n"); +#endif + } + if (dwFlags & MCI_TRACK) { + if (lpParms->dwTrack > CDADev[wDevID].nTracks) + return MCIERR_OUTOFRANGE; + lpParms->dwReturn = CDADev[wDevID].lpdwTrackPos[lpParms->dwTrack - 1]; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciStatus // get MCI_TRACK #%u !\n", lpParms->dwTrack); +#endif + } + lpParms->dwReturn = CDAUDIO_CalcTime(wDevID, + CDADev[wDevID].dwTimeFormat, lpParms->dwReturn); +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciStatus // MCI_STATUS_POSITION=%08X !\n", + lpParms->dwReturn); +#endif + return 0; + case MCI_STATUS_READY: + printf("CDAUDIO_mciStatus // MCI_STATUS_READY !\n"); + lpParms->dwReturn = TRUE; + return 0; + case MCI_STATUS_TIME_FORMAT: + printf("CDAUDIO_mciStatus // MCI_STATUS_TIME_FORMAT !\n"); + lpParms->dwReturn = MCI_FORMAT_MILLISECONDS; + return 0; + default: + printf("CDAUDIO_mciStatus // unknowm command %04X !\n", lpParms->dwItem); + return MCIERR_UNRECOGNIZED_COMMAND; + } + } + printf("CDAUDIO_mciStatus // not MCI_STATUS_ITEM !\n"); + return 0; +} + + +/************************************************************************** +* CDAUDIO_CalcTime [internal] +*/ +DWORD CDAUDIO_CalcTime(UINT wDevID, DWORD dwFormatType, DWORD dwFrame) +{ + DWORD dwTime = 0; + UINT wTrack; + UINT wMinutes; + UINT wSeconds; + UINT wFrames; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_CalcTime(%u, %08X, %lu);\n", wDevID, dwFormatType, dwFrame); +#endif +TryAGAIN: + switch (dwFormatType) { + case MCI_FORMAT_MILLISECONDS: + dwTime = dwFrame / CDFRAMES_PERSEC * 1000; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_CalcTime // MILLISECONDS %u\n", dwTime); +#endif + break; + case MCI_FORMAT_MSF: + wMinutes = dwFrame / CDFRAMES_PERMIN; + wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC; + wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - + CDFRAMES_PERSEC * wSeconds; + dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames); +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_CalcTime // MSF %02u:%02u:%02u -> dwTime=%u\n", + wMinutes, wSeconds, wFrames, dwTime); +#endif + break; + case MCI_FORMAT_TMSF: + for (wTrack = 0; wTrack < CDADev[wDevID].nTracks; wTrack++) { +/* dwTime += CDADev[wDevID].lpdwTrackLen[wTrack - 1]; + printf("Adding trk#%u curpos=%u \n", dwTime); + if (dwTime >= dwFrame) break; */ + if (CDADev[wDevID].lpdwTrackPos[wTrack - 1] >= dwFrame) break; + } + wMinutes = dwFrame / CDFRAMES_PERMIN; + wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC; + wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - + CDFRAMES_PERSEC * wSeconds; + dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames); +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_CalcTime // %02u-%02u:%02u:%02u\n", + wTrack, wMinutes, wSeconds, wFrames); +#endif + break; + default: + /* unknown format ! force TMSF ! ... */ + dwFormatType = MCI_FORMAT_TMSF; + goto TryAGAIN; + } + return dwTime; +} + + +/************************************************************************** +* CDAUDIO_CalcFrame [internal] +*/ +DWORD CDAUDIO_CalcFrame(UINT wDevID, DWORD dwFormatType, DWORD dwTime) +{ + DWORD dwFrame = 0; + UINT wTrack; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_CalcFrame(%u, %08X, %lu);\n", wDevID, dwFormatType, dwTime); +#endif +TryAGAIN: + switch (dwFormatType) { + case MCI_FORMAT_MILLISECONDS: + dwFrame = dwTime * CDFRAMES_PERSEC / 1000; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_CalcFrame // MILLISECONDS %u\n", dwFrame); +#endif + break; + case MCI_FORMAT_MSF: +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_CalcFrame // MSF %02u:%02u:%02u\n", + MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime), + MCI_MSF_FRAME(dwTime)); +#endif + dwFrame += CDFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime); + dwFrame += CDFRAMES_PERSEC * MCI_MSF_SECOND(dwTime); + dwFrame += MCI_MSF_FRAME(dwTime); + break; + case MCI_FORMAT_TMSF: + wTrack = MCI_TMSF_TRACK(dwTime); +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_CalcFrame // TMSF %02u-%02u:%02u:%02u\n", + MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime), + MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime)); + printf("CDAUDIO_CalcFrame // TMSF trackpos[%u]=%u\n", + wTrack, CDADev[wDevID].lpdwTrackPos[wTrack - 1]); +#endif + dwFrame = CDADev[wDevID].lpdwTrackPos[wTrack - 1]; + dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime); + dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime); + dwFrame += MCI_TMSF_FRAME(dwTime); + break; + default: + /* unknown format ! force TMSF ! ... */ + dwFormatType = MCI_FORMAT_TMSF; + goto TryAGAIN; + } + return dwFrame; +} + + +/************************************************************************** +* CDAUDIO_GetNumberOfTracks [internal] +*/ +UINT CDAUDIO_GetNumberOfTracks(UINT wDevID) +{ + struct cdrom_tochdr hdr; + if (CDADev[wDevID].nTracks == 0) { + if (ioctl(CDADev[wDevID].unixdev, CDROMREADTOCHDR, &hdr)) { + printf("GetNumberOfTracks(%u) // Error occured !\n", wDevID); + return (WORD)-1; + } + CDADev[wDevID].nTracks = hdr.cdth_trk1; + } + return CDADev[wDevID].nTracks; +} + +/************************************************************************** +* CDAUDIO_GetNumberOfTracks [internal] +*/ +BOOL CDAUDIO_GetTracksInfo(UINT wDevID) +{ + int i, length; + int start, last_start; + int total_length = 0; + struct cdrom_tocentry entry; + if (CDADev[wDevID].nTracks == 0) { + if (CDAUDIO_GetNumberOfTracks(wDevID) == (WORD)-1) return FALSE; + } + if (CDADev[wDevID].lpdwTrackLen != NULL) + free(CDADev[wDevID].lpdwTrackLen); + CDADev[wDevID].lpdwTrackLen = (LPDWORD)malloc( + (CDADev[wDevID].nTracks + 1) * sizeof(DWORD)); + if (CDADev[wDevID].lpdwTrackPos != NULL) + free(CDADev[wDevID].lpdwTrackPos); + CDADev[wDevID].lpdwTrackPos = (LPDWORD)malloc( + (CDADev[wDevID].nTracks + 1) * sizeof(DWORD)); + if (CDADev[wDevID].lpdwTrackLen == NULL || + CDADev[wDevID].lpdwTrackPos == NULL) { + printf("CDAUDIO_GetTracksInfo // error allocating track table !\n"); + return FALSE; + } + memset(CDADev[wDevID].lpdwTrackLen, 0, + (CDADev[wDevID].nTracks + 1) * sizeof(DWORD)); + memset(CDADev[wDevID].lpdwTrackPos, 0, + (CDADev[wDevID].nTracks + 1) * sizeof(DWORD)); + for (i = 0; i <= CDADev[wDevID].nTracks; i++) { + if (i == CDADev[wDevID].nTracks) + entry.cdte_track = CDROM_LEADOUT; + else + entry.cdte_track = i + 1; + entry.cdte_format = CDROM_MSF; + if (ioctl(CDADev[wDevID].unixdev, CDROMREADTOCENTRY, &entry)) { + printf("CDAUDIO_GetTracksInfo // error read entry\n"); + return FALSE; + } + start = CDFRAMES_PERSEC * (SECONDS_PERMIN * + entry.cdte_addr.msf.minute + entry.cdte_addr.msf.second) + + entry.cdte_addr.msf.frame; + if (i == 0) { + CDADev[wDevID].dwFirstOffset = last_start = start; + printf("CDAUDIO_GetTracksInfo // dwFirstOffset=%u\n", start); + } + else { + length = start - last_start; + last_start = start; + start = last_start - length; + total_length += length; + CDADev[wDevID].lpdwTrackLen[i - 1] = length; + CDADev[wDevID].lpdwTrackPos[i - 1] = start; + printf("CDAUDIO_GetTracksInfo // track #%u start=%u len=%u\n", + i, start, length); + } + } + CDADev[wDevID].dwTotalLen = total_length; + printf("CDAUDIO_GetTracksInfo // total_len=%u\n", total_length); + return TRUE; +} + + +/************************************************************************** +* CDAUDIO_GetNumberOfTracks [internal] +*/ +BOOL CDAUDIO_GetCDStatus(UINT wDevID) +{ + int oldmode = CDADev[wDevID].mode; + CDADev[wDevID].sc.cdsc_format = CDROM_MSF; + if (ioctl(CDADev[wDevID].unixdev, CDROMSUBCHNL, &CDADev[wDevID].sc)) { +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_GetCDStatus // opened or no_media !\n"); +#endif + CDADev[wDevID].mode = MCI_MODE_OPEN; + return TRUE; + } + switch (CDADev[wDevID].sc.cdsc_audiostatus) { + case CDROM_AUDIO_INVALID: + printf("CDAUDIO_GetCDStatus // device doesn't support status !\n"); + return FALSE; + case CDROM_AUDIO_NO_STATUS: + CDADev[wDevID].mode = MCI_MODE_STOP; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_GetCDStatus // MCI_MODE_STOP !\n"); +#endif + break; + case CDROM_AUDIO_PLAY: + CDADev[wDevID].mode = MCI_MODE_PLAY; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_GetCDStatus // MCI_MODE_PLAY !\n"); +#endif + break; + case CDROM_AUDIO_PAUSED: + CDADev[wDevID].mode = MCI_MODE_PAUSE; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_GetCDStatus // MCI_MODE_PAUSE !\n"); +#endif + break; + default: + printf("CDAUDIO_GetCDStatus // status=%02X !\n", + CDADev[wDevID].sc.cdsc_audiostatus); + } + CDADev[wDevID].nCurTrack = CDADev[wDevID].sc.cdsc_trk; + CDADev[wDevID].dwCurFrame = + CDFRAMES_PERMIN * CDADev[wDevID].sc.cdsc_absaddr.msf.minute + + CDFRAMES_PERSEC * CDADev[wDevID].sc.cdsc_absaddr.msf.second + + CDADev[wDevID].sc.cdsc_absaddr.msf.frame; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_GetCDStatus // %02u-%02u:%02u:%02u \n", + CDADev[wDevID].sc.cdsc_trk, + CDADev[wDevID].sc.cdsc_absaddr.msf.minute, + CDADev[wDevID].sc.cdsc_absaddr.msf.second, + CDADev[wDevID].sc.cdsc_absaddr.msf.frame); +#endif + if (oldmode != CDADev[wDevID].mode && oldmode == MCI_MODE_OPEN) { + if (!CDAUDIO_GetTracksInfo(wDevID)) { + printf("CDAUDIO_GetCDStatus // error updating TracksInfo !\n"); + return MCIERR_INTERNAL; + } + } + return TRUE; +} + +/************************************************************************** +* CDAUDIO_mciPlay [internal] +*/ +DWORD CDAUDIO_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) +{ + int start, end; + struct cdrom_msf msf; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciPlay(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + if (CDADev[wDevID].unixdev == 0) return MMSYSERR_NOTENABLED; + start = 0; end = CDADev[wDevID].dwTotalLen; + CDADev[wDevID].nCurTrack = 1; + if (dwFlags & MCI_FROM) { + start = CDAUDIO_CalcFrame(wDevID, + CDADev[wDevID].dwTimeFormat, lpParms->dwFrom); +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciPlay // MCI_FROM=%08X -> %u \n", + lpParms->dwFrom, start); +#endif + } + if (dwFlags & MCI_TO) { + end = CDAUDIO_CalcFrame(wDevID, + CDADev[wDevID].dwTimeFormat, lpParms->dwTo); +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciPlay // MCI_TO=%08X -> %u \n", + lpParms->dwTo, end); +#endif + } + start += CDADev[wDevID].dwFirstOffset; + end += CDADev[wDevID].dwFirstOffset; + msf.cdmsf_min0 = start / CDFRAMES_PERMIN; + msf.cdmsf_sec0 = (start % CDFRAMES_PERMIN) / CDFRAMES_PERSEC; + msf.cdmsf_frame0 = start % CDFRAMES_PERSEC; + msf.cdmsf_min1 = end / CDFRAMES_PERMIN; + msf.cdmsf_sec1 = (end % CDFRAMES_PERMIN) / CDFRAMES_PERSEC; + msf.cdmsf_frame1 = end % CDFRAMES_PERSEC; + if (ioctl(CDADev[wDevID].unixdev, CDROMSTART)) { + printf("CDAUDIO_mciPlay // motor doesn't start !\n"); + return MCIERR_HARDWARE; + } + if (ioctl(CDADev[wDevID].unixdev, CDROMPLAYMSF, &msf)) { + printf("CDAUDIO_mciPlay // device doesn't play !\n"); + return MCIERR_HARDWARE; + } +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciPlay // msf = %d:%d:%d %d:%d:%d\n", + msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0, + msf.cdmsf_min1, msf.cdmsf_sec1, msf.cdmsf_frame1); +#endif + CDADev[wDevID].mode = MCI_MODE_PLAY; + if (dwFlags & MCI_NOTIFY) { + printf("CDAUDIO_mciPlay // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + +/************************************************************************** +* CDAUDIO_mciStop [internal] +*/ +DWORD CDAUDIO_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) +{ +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciStop(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + if (ioctl(CDADev[wDevID].unixdev, CDROMSTOP)) return MCIERR_HARDWARE; + CDADev[wDevID].mode = MCI_MODE_STOP; + if (dwFlags & MCI_NOTIFY) { + printf("CDAUDIO_mciStop // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + +/************************************************************************** +* CDAUDIO_mciPause [internal] +*/ +DWORD CDAUDIO_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) +{ +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciPause(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + if (ioctl(CDADev[wDevID].unixdev, CDROMPAUSE)) return MCIERR_HARDWARE; + CDADev[wDevID].mode = MCI_MODE_PAUSE; + if (dwFlags & MCI_NOTIFY) { + printf("CDAUDIO_mciPause // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + +/************************************************************************** +* CDAUDIO_mciResume [internal] +*/ +DWORD CDAUDIO_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) +{ +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciResume(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + if (ioctl(CDADev[wDevID].unixdev, CDROMRESUME)) return MCIERR_HARDWARE; + CDADev[wDevID].mode = MCI_MODE_STOP; + if (dwFlags & MCI_NOTIFY) { + printf("CDAUDIO_mciResume // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + +/************************************************************************** +* CDAUDIO_mciSeek [internal] +*/ +DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms) +{ + DWORD dwRet; + MCI_PLAY_PARMS PlayParms; +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciSeek(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; + if (ioctl(CDADev[wDevID].unixdev, CDROMRESUME)) return MCIERR_HARDWARE; + CDADev[wDevID].mode = MCI_MODE_SEEK; + switch(dwFlags) { + case MCI_SEEK_TO_START: + PlayParms.dwFrom = 0; + break; + case MCI_SEEK_TO_END: + PlayParms.dwFrom = CDADev[wDevID].dwTotalLen; + break; + case MCI_TO: + PlayParms.dwFrom = lpParms->dwTo; + break; + } + dwRet = CDAUDIO_mciPlay(wDevID, MCI_WAIT | MCI_FROM, &PlayParms); + if (dwRet != 0) return dwRet; + dwRet = CDAUDIO_mciStop(wDevID, MCI_WAIT, (LPMCI_GENERIC_PARMS)&PlayParms); + if (dwFlags & MCI_NOTIFY) { + printf("CDAUDIO_mciSeek // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return dwRet; +} + + +/************************************************************************** +* CDAUDIO_mciSet [internal] +*/ +DWORD CDAUDIO_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms) +{ +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciSet(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms); +#endif + if (lpParms == NULL) return MCIERR_INTERNAL; +/* + printf("CDAUDIO_mciSet // dwTimeFormat=%08X\n", lpParms->dwTimeFormat); + printf("CDAUDIO_mciSet // dwAudio=%08X\n", lpParms->dwAudio); +*/ + if (dwFlags & MCI_SET_TIME_FORMAT) { + switch (lpParms->dwTimeFormat) { + case MCI_FORMAT_MILLISECONDS: +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciSet // MCI_FORMAT_MILLISECONDS !\n"); +#endif + break; + case MCI_FORMAT_MSF: +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciSet // MCI_FORMAT_MSF !\n"); +#endif + break; + case MCI_FORMAT_TMSF: +#ifdef DEBUG_CDAUDIO + printf("CDAUDIO_mciSet // MCI_FORMAT_TMSF !\n"); +#endif + break; + default: + printf("CDAUDIO_mciSet // bad time format !\n"); + return MCIERR_BAD_TIME_FORMAT; + } + CDADev[wDevID].dwTimeFormat = lpParms->dwTimeFormat; + } + if (dwFlags & MCI_SET_DOOR_OPEN) { + printf("CDAUDIO_mciSet // MCI_SET_DOOR_OPEN !\n"); + if (ioctl(CDADev[wDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE; + CDADev[wDevID].nTracks = 0; + } + if (dwFlags & MCI_SET_DOOR_CLOSED) { + printf("CDAUDIO_mciSet // MCI_SET_DOOR_CLOSED !\n"); + if (ioctl(CDADev[wDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE; + CDADev[wDevID].nTracks = 0; + } + if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION; + if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION; + if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION; + if (dwFlags & MCI_NOTIFY) { + printf("CDAUDIO_mciSet // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback); + mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), + CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL); + } + return 0; +} + + +/************************************************************************** +* CDAUDIO_DriverProc [sample driver] +*/ +LRESULT CDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, + DWORD dwParam1, DWORD dwParam2) +{ + switch(wMsg) { + case DRV_LOAD: + return (LRESULT)1L; + case DRV_FREE: + return (LRESULT)1L; + case DRV_OPEN: + case MCI_OPEN_DRIVER: + case MCI_OPEN: + return CDAUDIO_mciOpen(dwParam1, (LPMCI_OPEN_PARMS)dwParam2); + case DRV_CLOSE: + case MCI_CLOSE_DRIVER: + case MCI_CLOSE: + return CDAUDIO_mciClose(dwDevID, dwParam1, + (LPMCI_GENERIC_PARMS)dwParam2); + case DRV_ENABLE: + return (LRESULT)1L; + case DRV_DISABLE: + return (LRESULT)1L; + case DRV_QUERYCONFIGURE: + return (LRESULT)1L; + case DRV_CONFIGURE: + MessageBox((HWND)NULL, "Sample MultiMedia Linux Driver !", + "MMLinux Driver", MB_OK); + return (LRESULT)1L; + case DRV_INSTALL: + return (LRESULT)DRVCNF_RESTART; + case DRV_REMOVE: + return (LRESULT)DRVCNF_RESTART; + case MCI_GETDEVCAPS: + return CDAUDIO_mciGetDevCaps(dwDevID, dwParam1, + (LPMCI_GETDEVCAPS_PARMS)dwParam2); + case MCI_INFO: + return CDAUDIO_mciInfo(dwDevID, dwParam1, + (LPMCI_INFO_PARMS)dwParam2); + case MCI_STATUS: + return CDAUDIO_mciStatus(dwDevID, dwParam1, + (LPMCI_STATUS_PARMS)dwParam2); + case MCI_SET: + return CDAUDIO_mciSet(dwDevID, dwParam1, + (LPMCI_SET_PARMS)dwParam2); + case MCI_PLAY: + return CDAUDIO_mciPlay(dwDevID, dwParam1, + (LPMCI_PLAY_PARMS)dwParam2); + case MCI_STOP: + return CDAUDIO_mciStop(dwDevID, dwParam1, + (LPMCI_GENERIC_PARMS)dwParam2); + case MCI_PAUSE: + return CDAUDIO_mciPause(dwDevID, dwParam1, + (LPMCI_GENERIC_PARMS)dwParam2); + case MCI_RESUME: + return CDAUDIO_mciResume(dwDevID, dwParam1, + (LPMCI_GENERIC_PARMS)dwParam2); + case MCI_SEEK: + return CDAUDIO_mciSeek(dwDevID, dwParam1, + (LPMCI_SEEK_PARMS)dwParam2); + case MCI_SET_DOOR_OPEN: + printf("CDAUDIO_DriverProc // MCI_SET_DOOR_OPEN !\n"); + if (ioctl(CDADev[dwDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE; + CDADev[dwDevID].nTracks = 0; + return 0; + case MCI_SET_DOOR_CLOSED: + printf("CDAUDIO_DriverProc // MCI_SET_DOOR_CLOSED !\n"); + if (ioctl(CDADev[dwDevID].unixdev, CDROMEJECT, 1)) return MCIERR_HARDWARE; + CDADev[dwDevID].nTracks = 0; + return 0; + default: + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); + } +} + + +/*-----------------------------------------------------------------------*/ + diff --git a/misc/mmaux.c b/misc/mmaux.c new file mode 100644 index 00000000000..64627d8ed2f --- /dev/null +++ b/misc/mmaux.c @@ -0,0 +1,116 @@ +/* + * Sample AUXILARY Wine Driver for Linux + * + * Copyright 1994 Martin Ayotte + */ + +static char Copyright[] = "Copyright Martin Ayotte, 1994"; + +#include "stdio.h" +#include "win.h" +#include "user.h" +#include "driver.h" +#include "mmsystem.h" + +#include +#include +#include + +#define SOUND_DEV "/dev/dsp" +#define MIXER_DEV "/dev/mixer" + +#ifdef SOUND_VERSION +#define IOCTL(a,b,c) ioctl(a,b,&c) +#else +#define IOCTL(a,b,c) (c = ioctl(a,b,c) ) +#endif + + +/*-----------------------------------------------------------------------*/ + + +/************************************************************************** +* AUX_GetDevCaps [internal] +*/ +DWORD AUX_GetDevCaps(WORD wDevID, LPAUXCAPS lpCaps, DWORD dwSize) +{ + int mixer; + int volume; + printf("AUX_GetDevCaps(%u, %08X, %u);\n", wDevID, lpCaps, dwSize); + if (lpCaps == NULL) return MMSYSERR_NOTENABLED; + if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) { + printf("AUX_GetDevCaps // mixer device not available !\n"); + return MMSYSERR_NOTENABLED; + } + if (ioctl(mixer, SOUND_MIXER_READ_LINE, &volume) == -1) { + printf("AUX_GetDevCaps // unable read mixer !\n"); + return MMSYSERR_NOTENABLED; + } + close(mixer); + return MMSYSERR_NOERROR; +} + + +/************************************************************************** +* AUX_GetVolume [internal] +*/ +DWORD AUX_GetVolume(WORD wDevID, DWORD dwParam) +{ + int mixer; + int volume; + printf("AUX_GetVolume(%u, %08X);\n", wDevID, dwParam); + if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) { + printf("Linux 'AUX_GetVolume' // mixer device not available !\n"); + return MMSYSERR_NOTENABLED; + } + if (ioctl(mixer, SOUND_MIXER_READ_LINE, &volume) == -1) { + printf("Linux 'AUX_GetVolume' // unable read mixer !\n"); + return MMSYSERR_NOTENABLED; + } + close(mixer); + return MMSYSERR_NOERROR; +} + +/************************************************************************** +* AUX_SetVolume [internal] +*/ +DWORD AUX_SetVolume(WORD wDevID, DWORD dwParam) +{ + int mixer; + int volume = 50; + printf("AUX_SetVolume(%u, %08X);\n", wDevID, dwParam); + if ((mixer = open(MIXER_DEV, O_RDWR)) < 0) { + printf("Linux 'AUX_SetVolume' // mixer device not available !\n"); + return MMSYSERR_NOTENABLED; + } + if (ioctl(mixer, SOUND_MIXER_WRITE_LINE, &volume) == -1) { + printf("Linux 'AUX_SetVolume' // unable set mixer !\n"); + return MMSYSERR_NOTENABLED; + } + close(mixer); + return MMSYSERR_NOERROR; +} + + +/************************************************************************** +* auxMessage [sample driver] +*/ +DWORD auxMessage(WORD wDevID, WORD wMsg, DWORD dwUser, + DWORD dwParam1, DWORD dwParam2) +{ + printf("auxMessage(%u, %04X, %08X, %08X, %08X);\n", + wDevID, wMsg, dwUser, dwParam1, dwParam2); + switch(wMsg) { + case AUXDM_GETDEVCAPS: + return AUX_GetDevCaps(wDevID, (LPAUXCAPS)dwParam1, dwParam2); + case AUXDM_GETNUMDEVS: + return 0L; + case AUXDM_GETVOLUME: + return AUX_GetVolume(wDevID, dwParam1); + case AUXDM_SETVOLUME: + return AUX_SetVolume(wDevID, dwParam1); + } + return MMSYSERR_NOTSUPPORTED; +} + + diff --git a/misc/mmsystem.c b/misc/mmsystem.c index 90fc2de9b9e..da5ad6fd6ae 100644 --- a/misc/mmsystem.c +++ b/misc/mmsystem.c @@ -7,7 +7,10 @@ static char Copyright[] = "Copyright Martin Ayotte, 1993"; #include "stdio.h" +#include +#include #include "win.h" +#include "user.h" #include "driver.h" #include "mmsystem.h" @@ -31,6 +34,8 @@ typedef TIMERENTRY *LPTIMERENTRY; static LPTIMERENTRY lpTimerList = NULL; +static MCI_OPEN_DRIVER_PARMS mciDrv[MAXMCIDRIVERS]; + UINT WINAPI midiGetErrorText(UINT uError, LPSTR lpText, UINT uSize); UINT WINAPI waveGetErrorText(UINT uError, LPSTR lpText, UINT uSize); @@ -50,9 +55,67 @@ int MMSYSTEM_WEP(HANDLE hInstance, WORD wDataSeg, */ BOOL WINAPI sndPlaySound(LPCSTR lpszSoundName, UINT uFlags) { - printf("EMPTY STUB !!! sndPlaySound // SoundName='%s' uFlags=%04X !\n", - lpszSoundName, uFlags); - return 0; + int hFile; + int count; + WAVEHDR WaveHdr; + PCMWAVEFORMAT WaveFormat; + WAVEOPENDESC WaveDesc; + DWORD dwRet; + char str[128]; + LPSTR ptr; + printf("sndPlaySound // SoundName='%s' uFlags=%04X !\n", + lpszSoundName, uFlags); + if (lpszSoundName == NULL) { + printf("sndPlaySound // Stop !\n"); + return FALSE; + } + hFile = open(lpszSoundName, O_RDONLY); + if (hFile == 0) { + printf("sndPlaySound // searching in SystemSound List !\n"); + GetProfileString("Sounds", (LPSTR)lpszSoundName, "", str, sizeof(str)); + if (strlen(str) == 0) return FALSE; + if ((ptr = strchr(str, ',')) != NULL) *ptr = '\0'; + hFile = open(str, O_RDONLY); + if (hFile == 0) { + printf("sndPlaySound // can't find SystemSound='%s' !\n", str); + return FALSE; + } + } + WaveDesc.hWave = 0; + WaveDesc.lpFormat = (LPWAVEFORMAT)&WaveFormat; + WaveFormat.wf.wFormatTag = WAVE_FORMAT_PCM; + WaveFormat.wBitsPerSample = 8; + WaveFormat.wf.nChannels = 1; + WaveFormat.wf.nSamplesPerSec = 11025; + WaveFormat.wf.nAvgBytesPerSec = 11025; + WaveFormat.wf.nBlockAlign = 1; + dwRet = wodMessage(0, WODM_OPEN, 0, (DWORD)&WaveDesc, CALLBACK_NULL); + if (dwRet != MMSYSERR_NOERROR) { + printf("sndPlaySound // can't open WaveOut device !\n"); + return FALSE; + } + WaveHdr.lpData = (LPSTR) malloc(64000); + WaveHdr.dwBufferLength = 64000; + WaveHdr.dwUser = 0L; + WaveHdr.dwFlags = 0L; + WaveHdr.dwLoops = 0L; + dwRet = wodMessage(0, WODM_PREPARE, 0, (DWORD)&WaveHdr, sizeof(WAVEHDR)); + if (dwRet != MMSYSERR_NOERROR) { + printf("sndPlaySound // can't prepare WaveOut device !\n"); + return FALSE; + } + while(TRUE) { + count = read(hFile, WaveHdr.lpData, WaveHdr.dwBufferLength); + if (count == 0) break; + WaveHdr.dwBytesRecorded = count; + wodMessage(0, WODM_WRITE, 0, (DWORD)&WaveHdr, sizeof(WAVEHDR)); + } + wodMessage(0, WODM_UNPREPARE, 0, (DWORD)&WaveHdr, sizeof(WAVEHDR)); + wodMessage(0, WODM_CLOSE, 0, 0L, 0L); + free(WaveHdr.lpData); + close(hFile); + + return TRUE; } /************************************************************************** @@ -87,7 +150,23 @@ void WINAPI OutputDebugStr(LPCSTR str) BOOL DriverCallback(DWORD dwCallBack, UINT uFlags, HANDLE hDev, WORD wMsg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) { - printf("EMPTY STUB !!! DriverCallback() !\n"); + printf("DriverCallback(%08X, %04X, %04X, %04X, %08X, %08X, %08X); !\n", + dwCallBack, uFlags, hDev, wMsg, dwUser, dwParam1, dwParam2); + switch(uFlags & DCB_TYPEMASK) { + case DCB_NULL: + printf("DriverCallback() // CALLBACK_NULL !\n"); + break; + case DCB_WINDOW: + printf("DriverCallback() // CALLBACK_WINDOW !\n"); + break; + case DCB_TASK: + printf("DriverCallback() // CALLBACK_TASK !\n"); + break; + case DCB_FUNCTION: + printf("DriverCallback() // CALLBACK_FUNCTION !\n"); + break; + } + return TRUE; } /************************************************************************** @@ -170,8 +249,11 @@ WORD JoySetCalibration(WORD wID) */ UINT WINAPI auxGetNumDevs() { + UINT count = 0; printf("auxGetNumDevs !\n"); - return 0; + count += auxMessage(0, AUXDM_GETNUMDEVS, 0L, 0L, 0L); + printf("auxGetNumDevs return %u \n", count); + return count; } /************************************************************************** @@ -474,25 +556,32 @@ msg# 543 : tmsf /************************************************************************** -* mciWaveOpen [internal] +* mciDriverNotify [MMSYSTEM.711] */ -DWORD mciWaveOpen(UINT wDevID, DWORD dwParam, LPMCI_WAVE_OPEN_PARMS lpParms) +BOOL WINAPI mciDriverNotify(HWND hWndCallBack, UINT wDevID, UINT wStatus) { - if (lpParms == NULL) return MCIERR_INTERNAL; - printf("mciWaveOpen(%04X, %08X, %08X)\n", wDevID, dwParam, lpParms); - return MCIERR_INTERNAL; + printf("mciDriverNotify(%04X, %u, %04X)\n", hWndCallBack, wDevID, wStatus); + PostMessage(hWndCallBack, MM_MCINOTIFY, wStatus, + MAKELONG(mciDrv[wDevID].wDeviceID, 0)); + return TRUE; } - /************************************************************************** * mciOpen [internal] */ -DWORD mciOpen(UINT wDevID, DWORD dwParam, LPMCI_OPEN_PARMS lpParms) +DWORD mciOpen(DWORD dwParam, LPMCI_OPEN_PARMS lpParms) { char str[128]; DWORD dwDevTyp = 0; + UINT wDevID = 1; + printf("mciOpen(%08X, %08X)\n", dwParam, lpParms); if (lpParms == NULL) return MCIERR_INTERNAL; - printf("mciOpen(%04X, %08X, %08X)\n", wDevID, dwParam, lpParms); + while(mciDrv[wDevID].wType != 0) { + if (++wDevID >= MAXMCIDRIVERS) { + printf("MCI_OPEN // MAXMCIDRIVERS reached !\n"); + return MCIERR_INTERNAL; + } + } if (dwParam & MCI_OPEN_TYPE) { if (lpParms->lpstrDeviceType == NULL) return MCIERR_INTERNAL; if (dwParam & MCI_OPEN_TYPE_ID) { @@ -519,13 +608,17 @@ DWORD mciOpen(UINT wDevID, DWORD dwParam, LPMCI_OPEN_PARMS lpParms) dwDevTyp = MCI_DEVTYPE_ANIMATION; } } + mciDrv[wDevID].wType = dwDevTyp; + mciDrv[wDevID].wDeviceID = 1; + lpParms->wDeviceID = wDevID; + printf("MCI_OPEN // wDeviceID=%04X !\n", lpParms->wDeviceID); switch(dwDevTyp) { case MCI_DEVTYPE_CD_AUDIO: - printf("MCI_OPEN // No SEQUENCER yet !\n"); - return MCIERR_DEVICE_NOT_INSTALLED; + return CDAUDIO_DriverProc(0, 0, MCI_OPEN_DRIVER, + dwParam, (DWORD)lpParms); case MCI_DEVTYPE_WAVEFORM_AUDIO: - printf("MCI_OPEN // No WAVEAUDIO yet !\n"); - return MCIERR_DEVICE_NOT_INSTALLED; + return WAVE_DriverProc(0, 0, MCI_OPEN_DRIVER, + dwParam, (DWORD)lpParms); case MCI_DEVTYPE_SEQUENCER: printf("MCI_OPEN // No SEQUENCER yet !\n"); return MCIERR_DEVICE_NOT_INSTALLED; @@ -539,18 +632,35 @@ DWORD mciOpen(UINT wDevID, DWORD dwParam, LPMCI_OPEN_PARMS lpParms) printf("MCI_OPEN // Invalid Device Name '%08X' !\n", lpParms->lpstrDeviceType); return MCIERR_INVALID_DEVICE_NAME; } - lpParms->wDeviceID = ++mciActiveDev; - printf("MCI_OPEN // wDeviceID=%04X !\n", lpParms->wDeviceID); - return 0; - } - if (dwParam & MCI_OPEN_ELEMENT) { - printf("MCI_OPEN // Element !\n"); - printf("MCI_OPEN // Elem=%s' !\n", lpParms->lpstrElementName); } return MCIERR_INTERNAL; } +/************************************************************************** +* mciClose [internal] +*/ +DWORD mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms) +{ + DWORD dwRet = MCIERR_INTERNAL; + printf("mciClose(%u, %08X, %08X)\n", wDevID, dwParam, lpParms); + switch(mciDrv[wDevID].wType) { + case MCI_DEVTYPE_CD_AUDIO: + dwRet = CDAUDIO_DriverProc(mciDrv[wDevID].wDeviceID, 0, + MCI_CLOSE, dwParam, (DWORD)lpParms); + break; + case MCI_DEVTYPE_WAVEFORM_AUDIO: + dwRet = WAVE_DriverProc(mciDrv[wDevID].wDeviceID, 0, + MCI_CLOSE, dwParam, (DWORD)lpParms); + break; + default: + printf("mciClose() // unknown type=%04X !\n", mciDrv[wDevID].wType); + } + mciDrv[wDevID].wType = 0; + return dwRet; +} + + /************************************************************************** * mciSound [internal] */ @@ -563,106 +673,36 @@ DWORD mciSound(UINT wDevID, DWORD dwParam, LPMCI_SOUND_PARMS lpParms) } -/************************************************************************** -* mciGetDevCaps [internal] -*/ -DWORD mciGetDevCaps(UINT wDevID, DWORD dwParam, LPMCI_GETDEVCAPS_PARMS lpParms) -{ - if (lpParms == NULL) return MCIERR_INTERNAL; - lpParms->dwReturn = 0; - return 0; -} - - -/************************************************************************** -* mciInfo [internal] -*/ -DWORD mciInfo(UINT wDevID, DWORD dwParam, LPMCI_INFO_PARMS lpParms) -{ - if (lpParms == NULL) return MCIERR_INTERNAL; - lpParms->lpstrReturn = NULL; - lpParms->dwRetSize = 0; - return 0; -} - - -/************************************************************************** -* mciStatus [internal] -*/ -DWORD mciStatus(UINT wDevID, DWORD dwParam, LPMCI_STATUS_PARMS lpParms) -{ - if (lpParms == NULL) return MCIERR_INTERNAL; - return 0; -} - - -/************************************************************************** -* mciPlay [internal] -*/ -DWORD mciPlay(UINT wDevID, DWORD dwParam, LPMCI_PLAY_PARMS lpParms) -{ - if (lpParms == NULL) return MCIERR_INTERNAL; - return 0; -} - - -/************************************************************************** -* mciRecord [internal] -*/ -DWORD mciRecord(UINT wDevID, DWORD dwParam, LPMCI_RECORD_PARMS lpParms) -{ - if (lpParms == NULL) return MCIERR_INTERNAL; - return 0; -} - - -/************************************************************************** -* mciClose [internal] -*/ -DWORD mciClose(UINT wDevID) -{ - return 0; -} - /************************************************************************** * mciSendCommand [MMSYSTEM.701] */ DWORD mciSendCommand(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2) { + HDRVR hDrv = 0; +#ifdef DEBUG_MCI printf("mciSendCommand(%04X, %04X, %08X, %08X)\n", wDevID, wMsg, dwParam1, dwParam2); +#endif switch(wMsg) { case MCI_OPEN: - printf("mciSendCommand // MCI_OPEN !\n"); - if (dwParam1 & MCI_WAVE_OPEN_BUFFER) - return mciWaveOpen(wDevID, dwParam1, - (LPMCI_WAVE_OPEN_PARMS)dwParam2); - else - return mciOpen(wDevID, dwParam1, (LPMCI_OPEN_PARMS)dwParam2); - case MCI_PLAY: - printf("mciSendCommand // MCI_PLAY !\n"); - return mciPlay(wDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2); - case MCI_RECORD: - printf("mciSendCommand // MCI_RECORD !\n"); - return mciRecord(wDevID, dwParam1, (LPMCI_RECORD_PARMS)dwParam2); + return mciOpen(dwParam1, (LPMCI_OPEN_PARMS)dwParam2); case MCI_CLOSE: - printf("mciSendCommand // MCI_CLOSE !\n"); - return mciClose(wDevID); - case MCI_SOUND: - printf("mciSendCommand // MCI_SOUND !\n"); - return mciSound(wDevID, dwParam1, (LPMCI_SOUND_PARMS)dwParam2); - case MCI_STATUS: - printf("mciSendCommand // MCI_STATUS !\n"); - return mciStatus(wDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2); - case MCI_INFO: - printf("mciSendCommand // MCI_INFO !\n"); - return mciInfo(wDevID, dwParam1, (LPMCI_INFO_PARMS)dwParam2); - case MCI_GETDEVCAPS: - printf("mciSendCommand // MCI_GETDEVCAPS !\n"); - return mciGetDevCaps(wDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2); + return mciClose(wDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2); + default: + switch(mciDrv[wDevID].wType) { + case MCI_DEVTYPE_CD_AUDIO: + return CDAUDIO_DriverProc(mciDrv[wDevID].wDeviceID, hDrv, + wMsg, dwParam1, dwParam2); + case MCI_DEVTYPE_WAVEFORM_AUDIO: + return WAVE_DriverProc(mciDrv[wDevID].wDeviceID, hDrv, + wMsg, dwParam1, dwParam2); + default: + printf("mciSendCommand() // unknown type=%04X !\n", + mciDrv[wDevID].wType); + } } - return MCIERR_DEVICE_NOT_INSTALLED; + return MMSYSERR_INVALPARAM; } /************************************************************************** @@ -670,7 +710,13 @@ DWORD mciSendCommand(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2) */ UINT mciGetDeviceID (LPCSTR lpstrName) { + char str[128]; printf("mciGetDeviceID(%s)\n", lpstrName); + if (lpstrName != NULL) { + strcpy(str, lpstrName); + AnsiUpper(str); + if (strcmp(str, "ALL") == 0) return MCI_ALL_DEVICE_ID; + } return 0; } @@ -1046,8 +1092,11 @@ DWORD WINAPI midiInMessage(HMIDIIN hMidiIn, UINT uMessage, */ UINT WINAPI waveOutGetNumDevs() { + UINT count = 0; printf("waveOutGetNumDevs\n"); - return 1; + count += wodMessage(0, WODM_GETNUMDEVS, 0L, 0L, 0L); + printf("waveOutGetNumDevs return %u \n", count); + return count; } /************************************************************************** @@ -1056,7 +1105,7 @@ UINT WINAPI waveOutGetNumDevs() UINT WINAPI waveOutGetDevCaps(UINT uDeviceID, WAVEOUTCAPS FAR* lpCaps, UINT uSize) { printf("waveOutGetDevCaps\n"); - return MMSYSERR_INVALHANDLE; + return wodMessage(uDeviceID, WODM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize); } /************************************************************************** @@ -1144,20 +1193,42 @@ UINT WINAPI waveGetErrorText(UINT uError, LPSTR lpText, UINT uSize) UINT WINAPI waveOutOpen(HWAVEOUT FAR* lphWaveOut, UINT uDeviceID, const LPWAVEFORMAT lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags) { + HWAVE hWaveOut; + LPWAVEOPENDESC lpDesc; + DWORD dwRet; + BOOL bMapperFlg = FALSE; printf("waveOutOpen(%08X, %d, %08X, %08X, %08X, %08X);\n", lphWaveOut, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags); if (dwFlags & WAVE_FORMAT_QUERY) { - printf("waveOutOpen // WAVE_FORMAT_QUERY !\n"); - if (uDeviceID == (UINT)WAVE_MAPPER) { - printf("waveOutOpen // No WAVE_MAPPER supported yet !\n"); - return MMSYSERR_BADDEVICEID; - } + printf("waveOutOpen // WAVE_FORMAT_QUERY requested !\n"); + } + if (uDeviceID == (UINT)WAVE_MAPPER) { + printf("waveOutOpen // WAVE_MAPPER mode requested !\n"); + bMapperFlg = TRUE; + uDeviceID = 0; } if (lpFormat == NULL) return WAVERR_BADFORMAT; - if (lphWaveOut != NULL) *lphWaveOut = 0; - if (lphWaveOut != NULL) *lphWaveOut = ++mciActiveDev; - return 0; -/* return MMSYSERR_BADDEVICEID;*/ + hWaveOut = GlobalAlloc(GMEM_MOVEABLE, sizeof(WAVEOPENDESC)); + if (lphWaveOut != NULL) *lphWaveOut = hWaveOut; + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveOut); + if (lpDesc == NULL) return MMSYSERR_NOMEM; + lpDesc->hWave = hWaveOut; + lpDesc->lpFormat = lpFormat; + lpDesc->dwCallBack = dwCallback; + lpDesc->dwInstance = dwInstance; + while(uDeviceID < MAXWAVEDRIVERS) { + dwRet = wodMessage(uDeviceID, WODM_OPEN, + lpDesc->dwInstance, (DWORD)lpDesc, 0L); + if (dwRet == MMSYSERR_NOERROR) break; + if (!bMapperFlg) break; + uDeviceID++; + printf("waveOutOpen // WAVE_MAPPER mode ! try next driver...\n"); + } + if (dwFlags & WAVE_FORMAT_QUERY) { + printf("waveOutOpen // End of WAVE_FORMAT_QUERY !\n"); + waveOutClose(hWaveOut); + } + return dwRet; } /************************************************************************** @@ -1165,8 +1236,11 @@ UINT WINAPI waveOutOpen(HWAVEOUT FAR* lphWaveOut, UINT uDeviceID, */ UINT WINAPI waveOutClose(HWAVEOUT hWaveOut) { - printf("waveOutClose\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveOutClose(%04X)\n", hWaveOut); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveOut); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return wodMessage(0, WODM_CLOSE, lpDesc->dwInstance, 0L, 0L); } /************************************************************************** @@ -1175,8 +1249,13 @@ UINT WINAPI waveOutClose(HWAVEOUT hWaveOut) UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut, WAVEHDR FAR* lpWaveOutHdr, UINT uSize) { - printf("waveOutPrepareHeader\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveOutPrepareHeader(%04X, %08X, %u);\n", + hWaveOut, lpWaveOutHdr, uSize); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveOut); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return wodMessage(0, WODM_PREPARE, lpDesc->dwInstance, + (DWORD)lpWaveOutHdr, uSize); } /************************************************************************** @@ -1185,8 +1264,13 @@ UINT WINAPI waveOutPrepareHeader(HWAVEOUT hWaveOut, UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut, WAVEHDR FAR* lpWaveOutHdr, UINT uSize) { - printf("waveOutUnprepareHeader\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveOutUnprepareHeader(%04X, %08X, %u);\n", + hWaveOut, lpWaveOutHdr, uSize); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveOut); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return wodMessage(0, WODM_PREPARE, lpDesc->dwInstance, + (DWORD)lpWaveOutHdr, uSize); } /************************************************************************** @@ -1194,8 +1278,12 @@ UINT WINAPI waveOutUnprepareHeader(HWAVEOUT hWaveOut, */ UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, WAVEHDR FAR* lpWaveOutHdr, UINT uSize) { - printf("waveOutWrite\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveOutWrite(%04X, %08X, %u);\n", hWaveOut, lpWaveOutHdr, uSize); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveOut); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return wodMessage(0, WODM_WRITE, lpDesc->dwInstance, + (DWORD)lpWaveOutHdr, uSize); } /************************************************************************** @@ -1203,7 +1291,7 @@ UINT WINAPI waveOutWrite(HWAVEOUT hWaveOut, WAVEHDR FAR* lpWaveOutHdr, UINT uSi */ UINT WINAPI waveOutPause(HWAVEOUT hWaveOut) { - printf("waveOutPause\n"); + printf("waveOutPause(%04X)\n", hWaveOut); return MMSYSERR_INVALHANDLE; } @@ -1212,7 +1300,7 @@ UINT WINAPI waveOutPause(HWAVEOUT hWaveOut) */ UINT WINAPI waveOutRestart(HWAVEOUT hWaveOut) { - printf("waveOutRestart\n"); + printf("waveOutRestart(%04X)\n", hWaveOut); return MMSYSERR_INVALHANDLE; } @@ -1221,17 +1309,21 @@ UINT WINAPI waveOutRestart(HWAVEOUT hWaveOut) */ UINT WINAPI waveOutReset(HWAVEOUT hWaveOut) { - printf("waveOutReset\n"); + printf("waveOutReset(%04X)\n", hWaveOut); return MMSYSERR_INVALHANDLE; } /************************************************************************** * waveOutGetPosition [MMSYSTEM.412] */ -UINT WINAPI waveOutGetPosition(HWAVEOUT hWaveOut, MMTIME FAR* lpInfo, UINT uSize) +UINT WINAPI waveOutGetPosition(HWAVEOUT hWaveOut, MMTIME FAR* lpTime, UINT uSize) { - printf("waveOutGetPosition\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveOutGetPosition(%04X, %08X, %u);\n", hWaveOut, lpTime, uSize); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveOut); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return wodMessage(0, WODM_GETPOS, lpDesc->dwInstance, + (DWORD)lpTime, (DWORD)uSize); } /************************************************************************** @@ -1293,7 +1385,7 @@ UINT WINAPI waveOutSetPlaybackRate(HWAVEOUT hWaveOut, DWORD dwRate) */ UINT WINAPI waveOutBreakLoop(HWAVEOUT hWaveOut) { - printf("waveOutBreakLoop\n"); + printf("waveOutBreakLoop(%04X)\n", hWaveOut); return MMSYSERR_INVALHANDLE; } @@ -1319,8 +1411,11 @@ DWORD WINAPI waveOutMessage(HWAVEOUT hWaveOut, UINT uMessage, */ UINT WINAPI waveInGetNumDevs() { + UINT count = 0; printf("waveInGetNumDevs\n"); - return 0; + count += widMessage(0, WIDM_GETNUMDEVS, 0L, 0L, 0L); + printf("waveInGetNumDevs return %u \n", count); + return count; } @@ -1330,7 +1425,7 @@ UINT WINAPI waveInGetNumDevs() UINT WINAPI waveInGetDevCaps(UINT uDeviceID, WAVEINCAPS FAR* lpCaps, UINT uSize) { printf("waveInGetDevCaps\n"); - return MMSYSERR_INVALHANDLE; + return widMessage(uDeviceID, WIDM_GETDEVCAPS, 0L, (DWORD)lpCaps, uSize); } @@ -1350,18 +1445,42 @@ UINT WINAPI waveInGetErrorText(UINT uError, LPSTR lpText, UINT uSize) UINT WINAPI waveInOpen(HWAVEIN FAR* lphWaveIn, UINT uDeviceID, const LPWAVEFORMAT lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags) { + HWAVE hWaveIn; + LPWAVEOPENDESC lpDesc; + DWORD dwRet; + BOOL bMapperFlg = FALSE; printf("waveInOpen(%08X, %d, %08X, %08X, %08X, %08X);\n", lphWaveIn, uDeviceID, lpFormat, dwCallback, dwInstance, dwFlags); if (dwFlags & WAVE_FORMAT_QUERY) { - printf("waveInOpen // WAVE_FORMAT_QUERY !\n"); - if (uDeviceID == (UINT)WAVE_MAPPER) { - printf("waveInOpen // No WAVE_MAPPER supported yet !\n"); - return MMSYSERR_BADDEVICEID; - } + printf("waveInOpen // WAVE_FORMAT_QUERY requested !\n"); + } + if (uDeviceID == (UINT)WAVE_MAPPER) { + printf("waveInOpen // WAVE_MAPPER mode requested !\n"); + bMapperFlg = TRUE; + uDeviceID = 0; } - if (lphWaveIn != NULL) *lphWaveIn = 0; if (lpFormat == NULL) return WAVERR_BADFORMAT; - return MMSYSERR_BADDEVICEID; + hWaveIn = GlobalAlloc(GMEM_MOVEABLE, sizeof(WAVEOPENDESC)); + if (lphWaveIn != NULL) *lphWaveIn = hWaveIn; + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_NOMEM; + lpDesc->hWave = hWaveIn; + lpDesc->lpFormat = lpFormat; + lpDesc->dwCallBack = dwCallback; + lpDesc->dwInstance = dwInstance; + while(uDeviceID < MAXWAVEDRIVERS) { + dwRet = widMessage(uDeviceID, WIDM_OPEN, + lpDesc->dwInstance, (DWORD)lpDesc, 0L); + if (dwRet == MMSYSERR_NOERROR) break; + if (!bMapperFlg) break; + uDeviceID++; + printf("waveInOpen // WAVE_MAPPER mode ! try next driver...\n"); + } + if (dwFlags & WAVE_FORMAT_QUERY) { + printf("waveInOpen // End of WAVE_FORMAT_QUERY !\n"); + waveInClose(hWaveIn); + } + return dwRet; } @@ -1370,8 +1489,11 @@ UINT WINAPI waveInOpen(HWAVEIN FAR* lphWaveIn, UINT uDeviceID, */ UINT WINAPI waveInClose(HWAVEIN hWaveIn) { - printf("waveInClose\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveInClose(%04X)\n", hWaveIn); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return widMessage(0, WIDM_CLOSE, lpDesc->dwInstance, 0L, 0L); } @@ -1381,8 +1503,18 @@ UINT WINAPI waveInClose(HWAVEIN hWaveIn) UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn, WAVEHDR FAR* lpWaveInHdr, UINT uSize) { - printf("waveInPrepareHeader\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveInPrepareHeader(%04X, %08X, %u);\n", + hWaveIn, lpWaveInHdr, uSize); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE; + lpWaveInHdr->lpNext = NULL; + lpWaveInHdr->dwBytesRecorded = 0; + printf("waveInPrepareHeader // lpData=%08X size=%u \n", + lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength); + return widMessage(0, WIDM_PREPARE, lpDesc->dwInstance, + (DWORD)lpWaveInHdr, uSize); } @@ -1392,20 +1524,36 @@ UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn, UINT WINAPI waveInUnprepareHeader(HWAVEIN hWaveIn, WAVEHDR FAR* lpWaveInHdr, UINT uSize) { - printf("waveInUnprepareHeader\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveInUnprepareHeader(%04X, %08X, %u);\n", + hWaveIn, lpWaveInHdr, uSize); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + USER_HEAP_FREE(HIWORD((DWORD)lpWaveInHdr->lpData)); + lpWaveInHdr->lpData = NULL; + lpWaveInHdr->lpNext = NULL; + return widMessage(0, WIDM_PREPARE, lpDesc->dwInstance, + (DWORD)lpWaveInHdr, uSize); } - /************************************************************************** * waveInAddBuffer [MMSYSTEM.508] */ UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn, WAVEHDR FAR* lpWaveInHdr, UINT uSize) { - printf("waveInAddBuffer\n"); - return 0; + LPWAVEOPENDESC lpDesc; + printf("waveInAddBuffer(%04X, %08X, %u);\n", hWaveIn, lpWaveInHdr, uSize); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + if (lpWaveInHdr == NULL) return MMSYSERR_INVALHANDLE; + lpWaveInHdr->lpNext = NULL; + lpWaveInHdr->dwBytesRecorded = 0; + printf("waveInAddBuffer // lpData=%08X size=%u \n", + lpWaveInHdr->lpData, lpWaveInHdr->dwBufferLength); + return widMessage(0, WIDM_ADDBUFFER, lpDesc->dwInstance, + (DWORD)lpWaveInHdr, uSize); } @@ -1414,8 +1562,11 @@ UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn, */ UINT WINAPI waveInStart(HWAVEIN hWaveIn) { - printf("waveInStart\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveInStart(%04X)\n", hWaveIn); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return widMessage(0, WIDM_START, lpDesc->dwInstance, 0L, 0L); } @@ -1424,8 +1575,11 @@ UINT WINAPI waveInStart(HWAVEIN hWaveIn) */ UINT WINAPI waveInStop(HWAVEIN hWaveIn) { - printf("waveInStop\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveInStop(%04X)\n", hWaveIn); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return widMessage(0, WIDM_STOP, lpDesc->dwInstance, 0L, 0L); } @@ -1434,18 +1588,25 @@ UINT WINAPI waveInStop(HWAVEIN hWaveIn) */ UINT WINAPI waveInReset(HWAVEIN hWaveIn) { - printf("waveInReset\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveInReset(%04X)\n", hWaveIn); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return widMessage(0, WIDM_RESET, lpDesc->dwInstance, 0L, 0L); } /************************************************************************** * waveInGetPosition [MMSYSTEM.512] */ -UINT WINAPI waveInGetPosition(HWAVEIN hWaveIn, MMTIME FAR* lpInfo, UINT uSize) +UINT WINAPI waveInGetPosition(HWAVEIN hWaveIn, MMTIME FAR* lpTime, UINT uSize) { - printf("waveInGetPosition\n"); - return MMSYSERR_INVALHANDLE; + LPWAVEOPENDESC lpDesc; + printf("waveInGetPosition(%04X, %08X, %u);\n", hWaveIn, lpTime, uSize); + lpDesc = (LPWAVEOPENDESC) GlobalLock(hWaveIn); + if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; + return widMessage(0, WIDM_GETPOS, lpDesc->dwInstance, + (DWORD)lpTime, (DWORD)uSize); } @@ -1455,6 +1616,7 @@ UINT WINAPI waveInGetPosition(HWAVEIN hWaveIn, MMTIME FAR* lpInfo, UINT uSize) UINT WINAPI waveInGetID(HWAVEIN hWaveIn, UINT FAR* lpuDeviceID) { printf("waveInGetID\n"); + if (lpuDeviceID == NULL) return MMSYSERR_INVALPARAM; return 0; } @@ -1540,7 +1702,7 @@ WORD timeSetEvent(WORD wDelay, WORD wResol, printf("timeSetEvent(%u, %u, %08X, %08X, %04X);\n", wDelay, wResol, lpFunc, dwUser, wFlags); if (!mmTimeStarted) StartMMTime(); - lpNewTimer = malloc(sizeof(TIMERENTRY)); + lpNewTimer = (LPTIMERENTRY) malloc(sizeof(TIMERENTRY)); if (lpNewTimer == NULL) return 0; while (lpTimer != NULL) { wNewID = max(wNewID, lpTimer->wTimerID); @@ -1628,8 +1790,10 @@ DWORD timeGetTime() */ HMMIO WINAPI mmioOpen(LPSTR szFileName, MMIOINFO FAR* lpmmioinfo, DWORD dwOpenFlags) { + int hFile; printf("mmioOpen('%s', %08X, %08X);\n", szFileName, lpmmioinfo, dwOpenFlags); - return 0; + hFile = _lopen(szFileName, dwOpenFlags); + return (HMMIO)hFile; } @@ -1640,6 +1804,7 @@ HMMIO WINAPI mmioOpen(LPSTR szFileName, MMIOINFO FAR* lpmmioinfo, DWORD dwOpenFl UINT WINAPI mmioClose(HMMIO hmmio, UINT uFlags) { printf("mmioClose(%04X, %04X);\n", hmmio, uFlags); + _lclose(hmmio); return 0; } @@ -1651,6 +1816,7 @@ UINT WINAPI mmioClose(HMMIO hmmio, UINT uFlags) LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch) { printf("mmioRead\n"); + _lread(hmmio, pch, cch); return 0; } @@ -1815,8 +1981,10 @@ LRESULT DrvClose(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2) */ LRESULT WINAPI DrvSendMessage(HDRVR hDriver, WORD msg, LPARAM lParam1, LPARAM lParam2) { + DWORD dwDevID = 0; printf("DrvSendMessage(%04X, %04X, %08X, %08X);\n", hDriver, msg, lParam1, lParam2); + return CDAUDIO_DriverProc(dwDevID, hDriver, msg, lParam1, lParam2); } /************************************************************************** diff --git a/miscemu/int2f.c b/miscemu/int2f.c index 0a7d14e6076..046337c6959 100644 --- a/miscemu/int2f.c +++ b/miscemu/int2f.c @@ -3,6 +3,9 @@ #include "msdos.h" #include "wine.h" +int do_int2f_16(struct sigcontext_struct *context); + + int do_int2f(struct sigcontext_struct *context) { switch((context->sc_eax >> 8) & 0xff) @@ -12,17 +15,41 @@ int do_int2f(struct sigcontext_struct *context) return 1; case 0x16: - switch(context->sc_eax & 0xff) - { - case 0x00: /* windows enhanced mode install check */ - /* don't return anything as we're running in standard mode */ - return 1; - - default: - } + return do_int2f_16(context); default: IntBarf(0x2f, context); }; return 1; } + + +int do_int2f_16(struct sigcontext_struct *context) +{ + switch(context->sc_eax & 0xff) { + case 0x00: + /* return 'major/minor' for MSWin 3.1 */ + printf("do_int2f_16 // return 'major/minor' for MSWin 3.1 !\n"); + context->sc_eax = 0x0310; + return 1; + case 0x86: + /* operating in protected mode under DPMI */ + printf("do_int2f_16 // operating in protected mode under DPMI !\n"); + context->sc_eax = 0x0000; + return 1; + case 0x87: + printf("do_int2f_16 // return DPMI flags !\n"); + context->sc_eax = 0x0000; /* DPMI Installed */ + context->sc_ebx = 0x0001; /* 32bits available */ + context->sc_ecx = 0x04; /* processor 486 */ + context->sc_edx = 0x0100; /* DPMI major/minor */ + context->sc_esi = 0; /* # of para. of DOS */ + /* extended private data */ + return 1; + default: + IntBarf(0x2f, context); + } + return 1; +} + + diff --git a/windows/class.c b/windows/class.c index 753ee0d2895..622afe1e598 100644 --- a/windows/class.c +++ b/windows/class.c @@ -91,7 +91,8 @@ ATOM RegisterClass( LPWNDCLASS class ) { CLASS * newClass, * prevClassPtr; HCLASS handle, prevClass; - + int classExtra; + #ifdef DEBUG_CLASS printf( "RegisterClass: wndproc=%08x hinst=%d name='%s' background %x\n", class->lpfnWndProc, class->hInstance, class->lpszClassName, @@ -110,20 +111,18 @@ ATOM RegisterClass( LPWNDCLASS class ) if (!(prevClassPtr->wc.style & CS_GLOBALCLASS)) return 0; } - /* bug for bug compatible */ - - if (class->cbClsExtra < 0) class->cbClsExtra = 0; - if (class->cbWndExtra < 0) class->cbWndExtra = 0; - /* Create class */ - handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CLASS)+class->cbClsExtra ); + classExtra = (class->cbClsExtra < 0) ? 0 : class->cbClsExtra; + handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CLASS) + classExtra ); if (!handle) return 0; newClass = (CLASS *) USER_HEAP_ADDR( handle ); - newClass->hNext = firstClass; - newClass->wMagic = CLASS_MAGIC; - newClass->cWindows = 0; - newClass->wc = *class; + newClass->hNext = firstClass; + newClass->wMagic = CLASS_MAGIC; + newClass->cWindows = 0; + newClass->wc = *class; + newClass->wc.cbWndExtra = (class->cbWndExtra < 0) ? 0 : class->cbWndExtra; + newClass->wc.cbClsExtra = classExtra; if (newClass->wc.style & CS_GLOBALCLASS) newClass->atomName = GlobalAddAtom( class->lpszClassName ); @@ -147,7 +146,7 @@ ATOM RegisterClass( LPWNDCLASS class ) } } - if (class->cbClsExtra) memset( newClass->wExtra, 0, class->cbClsExtra ); + if (classExtra) memset( newClass->wExtra, 0, classExtra ); firstClass = handle; return newClass->atomName; } diff --git a/windows/dc.c b/windows/dc.c index 947372d469b..056329a2195 100644 --- a/windows/dc.c +++ b/windows/dc.c @@ -105,7 +105,6 @@ static void DC_InitDC( HDC hdc ) SelectObject( hdc, dc->w.hFont ); XSetGraphicsExposures( XT_display, dc->u.x.gc, False ); CLIPPING_SetDeviceClipping( dc ); - FONT_SelectObject(dc, STOCK_SYSTEM_FIXED_FONT, NULL); } @@ -204,7 +203,7 @@ int DC_SetupGCForText( DC * dc ) if (!dc->u.x.font.fstruct) { - FONT_SelectObject(dc, STOCK_SYSTEM_FIXED_FONT, NULL); + FONT_SelectObject(dc, STOCK_SYSTEM_FONT, NULL); } val.function = DC_XROPfunction[dc->w.ROPmode-1]; val.foreground = dc->w.textPixel; @@ -235,6 +234,7 @@ HDC GetDCState( HDC hdc ) #endif memcpy( &newdc->w, &dc->w, sizeof(dc->w) ); + memcpy( &newdc->u.x.pen, &dc->u.x.pen, sizeof(dc->u.x.pen) ); newdc->saveLevel = 0; newdc->w.flags |= DC_SAVED; diff --git a/windows/dialog.c b/windows/dialog.c index 7edc656ffba..47ad5b4e56f 100644 --- a/windows/dialog.c +++ b/windows/dialog.c @@ -595,13 +595,13 @@ WORD IsDlgButtonChecked( HWND hwnd, WORD id ) */ void CheckRadioButton( HWND hwndDlg, WORD firstID, WORD lastID, WORD checkID ) { - HWND button = GetDlgItem( hwndDlg, firstID ); + HWND button = GetDlgItem( hwndDlg, lastID ); while (button != 0) { WND * wndPtr = WIN_FindWndPtr( button ); if (!wndPtr) break; SendMessage( button, BM_SETCHECK, (wndPtr->wIDmenu == checkID), 0 ); - if (wndPtr->wIDmenu == lastID) break; + if (wndPtr->wIDmenu == firstID) break; button = wndPtr->hwndNext; } } diff --git a/windows/graphics.c b/windows/graphics.c index 0d2392f503c..c21eff38450 100644 --- a/windows/graphics.c +++ b/windows/graphics.c @@ -153,6 +153,8 @@ BOOL GRAPH_DrawArc( HDC hdc, int left, int top, int right, int bottom, (double)(xend-xcenter)*(bottom-top) ); diff_angle = end_angle - start_angle; if (diff_angle < 0.0) diff_angle += 2*PI; + if (left > right) swap_int( &left, &right ); + if (top > bottom) swap_int( &top, &bottom ); XDrawArc( display, dc->u.x.drawable, dc->u.x.gc, dc->w.DCOrgX + left, dc->w.DCOrgY + top, diff --git a/windows/painting.c b/windows/painting.c index 65a17ca6ae2..abac9b5458b 100644 --- a/windows/painting.c +++ b/windows/painting.c @@ -45,13 +45,6 @@ HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps ) if (!(wndPtr->flags & WIN_ERASE_UPDATERGN)) lps->fErase = TRUE; else lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 ); - /* - * a BeginPaint should return with these objects set by default - */ - SelectObject(lps->hdc, STOCK_BLACK_PEN); - SelectObject(lps->hdc, STOCK_WHITE_BRUSH); - SelectObject(lps->hdc, STOCK_SYSTEM_FONT); - return lps->hdc; } diff --git a/windows/win.c b/windows/win.c index cc11dd19f9b..d768512ef5d 100644 --- a/windows/win.c +++ b/windows/win.c @@ -253,7 +253,10 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName, exStyle, className, windowName, style, x, y, width, height, parent, menu, instance, data); #endif - + /* 'soundrec.exe' has negative position ! + Why ? For now, here a patch : */ + if (x < 0) x = 0; + if (y < 0) y = 0; if (x == CW_USEDEFAULT) x = y = 0; if (width == CW_USEDEFAULT) { @@ -366,24 +369,15 @@ HWND CreateWindowEx( DWORD exStyle, LPSTR className, LPSTR windowName, else win_attr.backing_store = Always; - if (Options.nosaveunders) - win_attr.save_under = FALSE; - else - win_attr.save_under = TRUE; + win_attr.save_under = ((classPtr->wc.style & CS_SAVEBITS) != 0); - - /* set the background of all windows to be white, just like - * MS-Windows does (hopefully!) - */ - win_attr.background_pixel = WhitePixelOfScreen(screen); - wndPtr->window = XCreateWindow( display, parentPtr->window, x + parentPtr->rectClient.left - parentPtr->rectWindow.left, y + parentPtr->rectClient.top - parentPtr->rectWindow.top, width, height, 0, CopyFromParent, InputOutput, CopyFromParent, CWEventMask | CWOverrideRedirect | CWColormap | - CWSaveUnder | CWBackingStore | CWBackPixel, &win_attr ); + CWSaveUnder | CWBackingStore, &win_attr ); XStoreName( display, wndPtr->window, windowName );