source: sbliveos2/trunk/drv16/stream.cpp@ 175

Last change on this file since 175 was 166, checked in by sandervl, 24 years ago

update for new direct audio interface

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1/* $Id: stream.cpp 166 2001-03-22 18:13:01Z sandervl $ */
2
3/* SCCSID = %W% %E% */
4/****************************************************************************
5 * *
6 * Copyright (c) IBM Corporation 1994 - 1997. *
7 * *
8 * The following IBM OS/2 source code is provided to you solely for the *
9 * the purpose of assisting you in your development of OS/2 device drivers. *
10 * You may use this code in accordance with the IBM License Agreement *
11 * provided in the IBM Device Driver Source Kit for OS/2. *
12 * *
13 ****************************************************************************/
14/**@internal %W%
15 * @notes
16 * @version %I%
17 * @context Unless otherwise noted, all interfaces are Ring-0, 16-bit,
18 * <stack context>.
19 * @history
20 *
21 */
22#define INCL_NOPMAPI
23#define INCL_DOSERRORS // for ERROR_INVALID_FUNCTION
24#include <os2.h>
25#include <os2me.h>
26#include <audio.h>
27
28#include <include.h>
29#include <devhelp.h>
30
31#include "stream.hpp"
32#include "queue.hpp"
33#include "event.hpp"
34#include "strmbuff.hpp"
35#include <ossidc.h>
36
37PQUEUEHEAD pStreamList; // List head for Streams. Initialized during DD initilialization.
38
39void STREAM::ReturnBuffer(void)
40{
41 SHD_REPORTINT shdri; // structure used to return buffers to SHD
42 PSTREAMBUFFER temp = (PSTREAMBUFFER)qhDone.PopHead();
43
44 if (temp)
45 {
46 shdri.ulFunction = SHD_REPORT_INT;
47
48 // if this is a write (playback) then set the streamtype and
49 // tell the stream handler that we played all of the buffer.
50 if (ulStreamType & STREAM_WRITE) {
51 shdri.ulFlag = SHD_WRITE_COMPLETE;
52 shdri.ulStatus = temp->ulBuffsz;
53 }
54 // if this is a capture then tell the stream hamdler
55 // how much data we wrote to the buffer
56 else {
57 shdri.ulFlag = SHD_READ_COMPLETE;
58 shdri.ulStatus = temp->ulBuffpos;
59 }
60 shdri.hStream = hstream;
61 shdri.pBuffer = temp->pBuffptr;
62 shdri.ulStreamTime = GetCurrentTime();
63 pfnSHD(&shdri);
64 delete temp;
65 }
66}
67
68//
69// ReturnBuffers(void)
70// Return all buffers to MMPM.
71//
72void STREAM::ReturnBuffers(void)
73{
74 // move all buffers from the InProcess Queue to the Done Queue
75 while (qhInProcess.IsElements()) {
76 qhDone.PushOnTail(qhInProcess.PopHead());
77 }
78 // Return all the buffers on the Done Queue
79 while (qhDone.IsElements()) {
80 ReturnBuffer();
81 }
82}
83//
84// ProcessEvents
85// called by the Process at interrupt time to see if there are
86// any events that have timed out
87//
88void STREAM::ProcessEvents(void)
89{
90//SvL: BUGFIX: check all events
91#if 1
92 if (qhEvent.IsElements()) {
93 PEVENT pnextevent = (PEVENT)qhEvent.Head();
94 ULONG time = GetCurrentTime();
95 while(pnextevent) {
96 ULONG eventtime = pnextevent->GetEventTime();
97 if (eventtime <= time)
98 pnextevent->Report(time);
99 pnextevent = (PEVENT)pnextevent->pNext;
100 }
101 }
102#else
103 if (qhEvent.IsElements()) {
104 PEVENT pnextevent = (PEVENT)qhEvent.Head();
105 ULONG time = GetCurrentTime();
106 ULONG eventtime = pnextevent->GetEventTime();
107 if (eventtime <= time)
108 pnextevent->Report(time);
109 }
110#endif
111}
112
113ULONG STREAM::EnableEvent(PDDCMDCONTROL pControl)
114{
115
116 // see if the event already exists on the event queue
117 // call FindEvent if we get back an address (event exists)
118 // call the UpdateEvent member function and get the event info updated.
119 // if Findevent returns NULL (no event on queue) then call the construct
120 // a new event and put it on the tail of the event queue. then call
121 // SetNextEvent to update the next event to time out....
122
123 PEVENT pevent = FindEvent(pControl->hEvent, &qhEvent);
124 if (pevent)
125 pevent->UpdateEvent(this,pControl->hEvent,(PCONTROL_PARM)pControl->pParm);
126 else {
127 pevent= new EVENT(this,pControl->hEvent,(PCONTROL_PARM)pControl->pParm);
128 }
129 if (!pevent)
130 return ERROR_TOO_MANY_EVENTS;
131
132 SetNextEvent();
133 return NO_ERROR;
134}
135
136ULONG STREAM::DisableEvent(PDDCMDCONTROL pControl)
137{
138 PEVENT pevent = FindEvent(pControl->hEvent, &qhEvent);
139 if (!pevent)
140 return ERROR_INVALID_EVENT;
141
142 // destroying an event may change things that get referenced in the ISR
143 // so we really need to cli/sti around the call to DestroyElement
144 cli();
145 qhEvent.DestroyElement((PQUEUEELEMENT)pevent);
146 if (qhEvent.Head() != qhEvent.Tail())
147 SetNextEvent();
148 sti();
149 return NO_ERROR;
150}
151
152ULONG STREAM::PauseStreamTime(void)
153{
154 fIncrementCounter = FALSE;
155 return NO_ERROR;
156}
157
158ULONG STREAM::ResumeStreamTime(void)
159{
160
161 fIncrementCounter = TRUE;
162 return NO_ERROR;
163}
164
165
166
167ULONG STREAM::Register(PDDCMDREGISTER p)
168{
169 hstream = p->hStream;
170 pfnSHD = (PFN_SHD) p->pSHDEntryPoint;
171 p->ulAddressType = ADDRESS_TYPE_LINEAR;
172 p->mmtimePerUnit = 0;
173 p->ulBytesPerUnit = 0;
174 p->ulNumBufs = 0x00000010;
175 if (ulStreamType & 0xFFFFFF60) // if this is a midi stream
176 p->ulBufSize = 0x00000200;
177 else
178 p->ulBufSize = 0x00004000;
179 return 0;
180}
181
182
183void STREAM::DeRegister(void)
184{
185 hstream = 0;
186 pfnSHD = NULL;
187}
188
189
190virtual ULONG STREAM::Write(PSTREAMBUF pbuf, ULONG uLength)
191{
192 qhInProcess.PushOnTail((PQUEUEELEMENT)new STREAMBUFFER(uLength, pbuf));
193 return 0;
194}
195
196/**@internal SetNextEvent
197 * @param None
198 * @return None
199 * @notes
200 * the function walks the event list and finds the next event to timeout.
201 * the event is moved to the head of the event queue.
202 *
203 */
204void STREAM::SetNextEvent(void)
205{
206
207 // if there are no events or only one event on the
208 // queue just return
209 if ((qhEvent.Head()) == (qhEvent.Tail()))
210 return;
211
212 PQUEUEELEMENT pele1 = qhEvent.Head();
213 PQUEUEELEMENT pele2 = NULL;
214 ULONG ulTimeToBeat = -1; // -1 equals 0xFFFFFFFF the maximum time
215
216 while (pele1) {
217 if (((PEVENT)pele1)->GetEventTime() <= ulTimeToBeat) {
218 pele2 = pele1;
219 ulTimeToBeat = ((PEVENT)pele1)->GetEventTime();
220 }
221 pele1 = pele1->pNext;
222 }
223 // pele2 should now contain the address of the next
224 // event to time out.. if it is not already on
225 // the head of the Event queue then put it there
226 if (pele2 != qhEvent.Head()) {
227 cli();
228 qhEvent.PopElement(pele2);
229 qhEvent.PushOnHead(pele2);
230 sti();
231 }
232}
233#define INVALID_HSTREAM ((HSTREAM) 0)
234#define INVALID_HFILE ((ULONG) 0)
235
236STREAM::STREAM(ULONG streamtype, USHORT filesysnum)
237{
238 // put this stream on the stream list
239 pStreamList->PushOnTail(this);
240
241 // get the pointer to the hardware object
242 pahw = GetHardwareDevice(streamtype);
243 ulStreamType = streamtype;
244
245 hstream = INVALID_HSTREAM; // We're putting a stream into the stream list, but
246 ulSysFileNum = filesysnum;
247
248 fIncrementCounter = TRUE;
249 ulCurrentTime = 0;
250 ulStreamState = STREAM_STOPPED;
251
252 ulStreamId = 0;
253
254 balance = 50; //middle
255 volume = 80;
256 inputgain = 50;
257 inputsrc = MIX_RECSRC_LINE;
258}
259
260STREAM::~STREAM(void)
261{
262 if (ulStreamState == STREAM_STREAMING)
263 pahw->Stop(this);
264 // detstoy all the STREAMBUFFERs and EVENTs that this STREAM
265 // may still have
266
267 while (qhInProcess.IsElements()) {
268 qhInProcess.DestroyElement(qhInProcess.Head());
269 } /* endwhile */
270
271 while (qhDone.IsElements()) {
272 qhDone.DestroyElement(qhDone.Head());
273 } /* endwhile */
274
275 while (qhEvent.IsElements()) {
276 qhEvent.DestroyElement(qhEvent.Head());
277 } /* endwhile */
278
279 pStreamList->PopElement(this);
280}
281
282void STREAM::SetInputSrc(int src) { inputsrc = src; }
283void STREAM::SetInputGain(ULONG gain) { inputgain = gain; }
284void STREAM::SetVolume(ULONG volume) { this->volume = volume; }
285void STREAM::SetBalance(ULONG balance) { this->balance = balance; }
286
287BOOL STREAM::SetMasterVol(ULONG volume)
288{
289 if(mastervol != volume) {
290 mastervol = volume;
291 return OSS16_SetMasterVol(this, volume);
292 }
293 return TRUE;
294}
295ULONG STREAM::mastervol = MAKE_VOLUME_LR(100, 100);
296
297PSTREAM FindActiveStream(ULONG StreamType)
298{
299 PSTREAM pStream = (PSTREAM) pStreamList->Head();
300
301 while (pStream)
302 if ((pStream->ulStreamType == StreamType) &&
303 (pStream->ulStreamState == STREAM_STREAMING))
304 return pStream;
305 else
306 pStream = (PSTREAM) pStream->pNext;
307
308 return NULL;
309}
310
311PSTREAM FindActiveStream(ULONG StreamType, ULONG StreamId)
312{
313 PSTREAM pStream = (PSTREAM) pStreamList->Head();
314
315 while (pStream)
316 if ((pStream->ulStreamType == StreamType) &&
317 (pStream->ulStreamState == STREAM_STREAMING) && (pStream->ulStreamId == StreamId))
318 return pStream;
319 else
320 pStream = (PSTREAM) pStream->pNext;
321
322 return NULL;
323}
324
325PSTREAM FindStream_fromFile(ULONG ulSysFileNum)
326/* Map a system file handle to a Stream object.
327 * ### FUTURE: Make parm type a real type so we can use overloading,
328 * ### and change name/signature back to "FindStream( fileHandle )".
329 */
330{
331 PSTREAM pStream = (PSTREAM) pStreamList->Head();
332
333 while (pStream)
334 if (pStream->ulSysFileNum == ulSysFileNum)
335 return pStream;
336 else
337 pStream = (PSTREAM) pStream->pNext;
338
339 return NULL;
340}
341
342PSTREAM FindStream(HSTREAM hStream)
343/* Map a stream handle to a Stream object. */
344{
345 PSTREAM pStream = (PSTREAM) pStreamList->Head();
346
347 while (pStream)
348 if (pStream->hstream == hStream)
349 return pStream;
350 else
351 pStream = (PSTREAM) pStream->pNext;
352
353 return NULL;
354}
Note: See TracBrowser for help on using the repository browser.