| 1 | /* $Id: waveinoutbase.cpp,v 1.7 2003-10-13 09:18:38 sandervl Exp $ */ | 
|---|
| 2 |  | 
|---|
| 3 | /* | 
|---|
| 4 | * Wave playback class (DART) | 
|---|
| 5 | * | 
|---|
| 6 | * Copyright 1998-2001 Sander van Leeuwen (sandervl@xs4all.nl) | 
|---|
| 7 | * | 
|---|
| 8 | * | 
|---|
| 9 | * Project Odin Software License can be found in LICENSE.TXT | 
|---|
| 10 | * | 
|---|
| 11 | * | 
|---|
| 12 | */ | 
|---|
| 13 |  | 
|---|
| 14 | /******************************************************************************/ | 
|---|
| 15 | // Includes | 
|---|
| 16 | /******************************************************************************/ | 
|---|
| 17 |  | 
|---|
| 18 | #define  INCL_BASE | 
|---|
| 19 | #define  INCL_OS2MM | 
|---|
| 20 | #include <os2wrap.h>   //Odin32 OS/2 api wrappers | 
|---|
| 21 | #include <os2mewrap.h> //Odin32 OS/2 MMPM/2 api wrappers | 
|---|
| 22 | #include <stdlib.h> | 
|---|
| 23 | #include <string.h> | 
|---|
| 24 | #define  OS2_ONLY | 
|---|
| 25 | #include <win32api.h> | 
|---|
| 26 | #include <wprocess.h> | 
|---|
| 27 |  | 
|---|
| 28 | #include "misc.h" | 
|---|
| 29 | #include "waveinoutbase.h" | 
|---|
| 30 |  | 
|---|
| 31 | #define DBG_LOCALLOG    DBG_waveinoutbase | 
|---|
| 32 | #include "dbglocal.h" | 
|---|
| 33 |  | 
|---|
| 34 | /******************************************************************************/ | 
|---|
| 35 | /******************************************************************************/ | 
|---|
| 36 |  | 
|---|
| 37 | VMutex      wavemutex; | 
|---|
| 38 | WaveInOut * WaveInOut::head = NULL; | 
|---|
| 39 |  | 
|---|
| 40 | /******************************************************************************/ | 
|---|
| 41 | /******************************************************************************/ | 
|---|
| 42 | WaveInOut::WaveInOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen, ULONG nCallback, ULONG dwInstance) | 
|---|
| 43 | { | 
|---|
| 44 | SampleRate    = pwfx->nSamplesPerSec; | 
|---|
| 45 | BitsPerSample = pwfx->wBitsPerSample; | 
|---|
| 46 | nChannels     = pwfx->nChannels; | 
|---|
| 47 | OpenFlags     = fdwOpen; | 
|---|
| 48 | Callback      = nCallback; | 
|---|
| 49 | Instance      = dwInstance; | 
|---|
| 50 | State         = STATE_STOPPED; | 
|---|
| 51 | queuedbuffers = 0; | 
|---|
| 52 | wavehdr       = NULL; | 
|---|
| 53 | next          = NULL; | 
|---|
| 54 |  | 
|---|
| 55 | dprintf(("WaveInOutOpen: samplerate %d, numChan %d bps %d (%d), format %x", SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag)); | 
|---|
| 56 |  | 
|---|
| 57 | wavemutex.enter(); | 
|---|
| 58 |  | 
|---|
| 59 | if(head == NULL) { | 
|---|
| 60 | head = this; | 
|---|
| 61 | } | 
|---|
| 62 | else { | 
|---|
| 63 | WaveInOut *dwave = head; | 
|---|
| 64 |  | 
|---|
| 65 | while(dwave->next) { | 
|---|
| 66 | dwave = dwave->next; | 
|---|
| 67 | } | 
|---|
| 68 | dwave->next = this; | 
|---|
| 69 | } | 
|---|
| 70 | wavemutex.leave(); | 
|---|
| 71 | } | 
|---|
| 72 | /******************************************************************************/ | 
|---|
| 73 | /******************************************************************************/ | 
|---|
| 74 | WaveInOut::~WaveInOut() | 
|---|
| 75 | { | 
|---|
| 76 | wavemutex.enter(); | 
|---|
| 77 |  | 
|---|
| 78 | State = STATE_STOPPED; | 
|---|
| 79 |  | 
|---|
| 80 | if(head == this) { | 
|---|
| 81 | head = this->next; | 
|---|
| 82 | } | 
|---|
| 83 | else { | 
|---|
| 84 | WaveInOut *dwave = head; | 
|---|
| 85 |  | 
|---|
| 86 | while(dwave->next != this) { | 
|---|
| 87 | dwave = dwave->next; | 
|---|
| 88 | } | 
|---|
| 89 | dwave->next = this->next; | 
|---|
| 90 | } | 
|---|
| 91 | wavemutex.leave(); | 
|---|
| 92 | } | 
|---|
| 93 | /******************************************************************************/ | 
|---|
| 94 | /******************************************************************************/ | 
|---|
| 95 | void WaveInOut::callback(UINT uMessage, DWORD dw1, DWORD dw2) | 
|---|
| 96 | { | 
|---|
| 97 | dprintf(("WINMM:WaveInOut::callback type %x, callback 0x%x (HDRVR h=%08xh, UINT uMessage=%08xh, DWORD dwUser=%08xh, DWORD dw1=%08xh, DWORD dw2=%08xh)", | 
|---|
| 98 | OpenFlags, Callback, this, uMessage, Instance, dw1, dw2)); | 
|---|
| 99 |  | 
|---|
| 100 | switch(OpenFlags & CALLBACK_TYPEMASK) { | 
|---|
| 101 | case CALLBACK_WINDOW: | 
|---|
| 102 | PostMessageA((HWND)Callback, uMessage, (WPARAM)this, dw1); | 
|---|
| 103 | break; | 
|---|
| 104 |  | 
|---|
| 105 | case CALLBACK_TASK: // == CALLBACK_THREAD | 
|---|
| 106 | PostThreadMessageA(Callback, uMessage, (WPARAM)this, dw1); | 
|---|
| 107 | break; | 
|---|
| 108 |  | 
|---|
| 109 | case CALLBACK_FUNCTION: | 
|---|
| 110 | { | 
|---|
| 111 | USHORT selTIB = GetFS(); // save current FS selector | 
|---|
| 112 | USHORT selCallback; | 
|---|
| 113 | LPDRVCALLBACK mthdCallback = (LPDRVCALLBACK)Callback; | 
|---|
| 114 |  | 
|---|
| 115 | if(selTIB == SELECTOR_OS2_FS) { | 
|---|
| 116 | selCallback = GetProcessTIBSel(); | 
|---|
| 117 | } | 
|---|
| 118 | else selCallback = selTIB; | 
|---|
| 119 |  | 
|---|
| 120 | //TODO: may not be very safe. perhaps we should allocate a new TIB for the DART thread or let another thread do the actual callback | 
|---|
| 121 | if(selCallback) | 
|---|
| 122 | { | 
|---|
| 123 | SetFS(selCallback);      // switch to callback win32 tib selector (stored in WaveInOutOpen) | 
|---|
| 124 |  | 
|---|
| 125 | //@@@PH 1999/12/28 Shockwave Flash seem to make assumptions on a | 
|---|
| 126 | // specific stack layout. Do we have the correct calling convention here? | 
|---|
| 127 | mthdCallback((HDRVR)this, uMessage, Instance, dw1, dw2); | 
|---|
| 128 | SetFS(selTIB);           // switch back to the saved FS selector | 
|---|
| 129 | } | 
|---|
| 130 | else { | 
|---|
| 131 | dprintf(("WARNING: no valid selector of main thread available (process exiting); skipping WaveInOut notify")); | 
|---|
| 132 | } | 
|---|
| 133 | break; | 
|---|
| 134 | } | 
|---|
| 135 |  | 
|---|
| 136 | case CALLBACK_EVENT: | 
|---|
| 137 | SetEvent((HANDLE)Callback); | 
|---|
| 138 | break; | 
|---|
| 139 |  | 
|---|
| 140 | case CALLBACK_NULL: | 
|---|
| 141 | break; //no callback | 
|---|
| 142 |  | 
|---|
| 143 | default: | 
|---|
| 144 | dprintf(("WARNING: Unknown callback type %x %x", OpenFlags, Callback)); | 
|---|
| 145 | break; | 
|---|
| 146 | } //switch | 
|---|
| 147 | dprintf2(("WINMM:WaveInOut::callback returned")); | 
|---|
| 148 | } | 
|---|
| 149 | /******************************************************************************/ | 
|---|
| 150 | //Delete all active wave objects | 
|---|
| 151 | /******************************************************************************/ | 
|---|
| 152 | void WaveInOut::shutdown() | 
|---|
| 153 | { | 
|---|
| 154 | dprintf(("WaveInOut::shutdown")); | 
|---|
| 155 | wavemutex.enter(); | 
|---|
| 156 | while(head) { | 
|---|
| 157 | delete head; | 
|---|
| 158 | } | 
|---|
| 159 | wavemutex.leave(); | 
|---|
| 160 | dprintf(("WaveInOut::shutdown end")); | 
|---|
| 161 | } | 
|---|
| 162 | /******************************************************************************/ | 
|---|
| 163 | /******************************************************************************/ | 
|---|
| 164 | BOOL WaveInOut::find(WaveInOut *dwave) | 
|---|
| 165 | { | 
|---|
| 166 | wavemutex.enter(); | 
|---|
| 167 |  | 
|---|
| 168 | WaveInOut *curwave = head; | 
|---|
| 169 |  | 
|---|
| 170 | while(curwave) { | 
|---|
| 171 | if(dwave == curwave) { | 
|---|
| 172 | wavemutex.leave(); | 
|---|
| 173 | return(TRUE); | 
|---|
| 174 | } | 
|---|
| 175 | curwave = curwave->next; | 
|---|
| 176 | } | 
|---|
| 177 | wavemutex.leave(); | 
|---|
| 178 |  | 
|---|
| 179 | dprintf2(("WINMM:WaveInOut not found!\n")); | 
|---|
| 180 | return(FALSE); | 
|---|
| 181 | } | 
|---|
| 182 | /******************************************************************************/ | 
|---|
| 183 | /******************************************************************************/ | 
|---|
| 184 |  | 
|---|