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

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

DirectAudio interface updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.8 KB
Line 
1/* $Id: stream.cpp 178 2001-04-30 21:08:00Z 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
190#pragma off (unreferenced)
191virtual ULONG STREAM::Write(PSTREAMBUF pbuf, ULONG uLength, BOOL fLooping)
192#pragma on (unreferenced)
193{
194 qhInProcess.PushOnTail((PQUEUEELEMENT)new STREAMBUFFER(uLength, pbuf));
195 return 0;
196}
197
198/**@internal SetNextEvent
199 * @param None
200 * @return None
201 * @notes
202 * the function walks the event list and finds the next event to timeout.
203 * the event is moved to the head of the event queue.
204 *
205 */
206void STREAM::SetNextEvent(void)
207{
208
209 // if there are no events or only one event on the
210 // queue just return
211 if ((qhEvent.Head()) == (qhEvent.Tail()))
212 return;
213
214 PQUEUEELEMENT pele1 = qhEvent.Head();
215 PQUEUEELEMENT pele2 = NULL;
216 ULONG ulTimeToBeat = -1; // -1 equals 0xFFFFFFFF the maximum time
217
218 while (pele1) {
219 if (((PEVENT)pele1)->GetEventTime() <= ulTimeToBeat) {
220 pele2 = pele1;
221 ulTimeToBeat = ((PEVENT)pele1)->GetEventTime();
222 }
223 pele1 = pele1->pNext;
224 }
225 // pele2 should now contain the address of the next
226 // event to time out.. if it is not already on
227 // the head of the Event queue then put it there
228 if (pele2 != qhEvent.Head()) {
229 cli();
230 qhEvent.PopElement(pele2);
231 qhEvent.PushOnHead(pele2);
232 sti();
233 }
234}
235#define INVALID_HSTREAM ((HSTREAM) 0)
236#define INVALID_HFILE ((ULONG) 0)
237
238STREAM::STREAM(ULONG streamtype, USHORT filesysnum)
239{
240 // put this stream on the stream list
241 pStreamList->PushOnTail(this);
242
243 // get the pointer to the hardware object
244 pahw = GetHardwareDevice(streamtype);
245 ulStreamType = streamtype;
246
247 hstream = INVALID_HSTREAM; // We're putting a stream into the stream list, but
248 ulSysFileNum = filesysnum;
249
250 fIncrementCounter = TRUE;
251 ulCurrentTime = 0;
252 ulStreamState = STREAM_STOPPED;
253
254 ulStreamId = 0;
255
256 balance = 50; //middle
257 volume = 80;
258 inputgain = 50;
259 inputsrc = MIX_RECSRC_LINE;
260}
261
262STREAM::~STREAM(void)
263{
264 if (ulStreamState == STREAM_STREAMING)
265 pahw->Stop(this);
266 // detstoy all the STREAMBUFFERs and EVENTs that this STREAM
267 // may still have
268
269 while (qhInProcess.IsElements()) {
270 qhInProcess.DestroyElement(qhInProcess.Head());
271 } /* endwhile */
272
273 while (qhDone.IsElements()) {
274 qhDone.DestroyElement(qhDone.Head());
275 } /* endwhile */
276
277 while (qhEvent.IsElements()) {
278 qhEvent.DestroyElement(qhEvent.Head());
279 } /* endwhile */
280
281 pStreamList->PopElement(this);
282}
283
284#pragma off (unreferenced)
285void STREAM::SetLooping(BOOL fLooping)
286#pragma on (unreferenced)
287{
288 return;
289}
290
291BOOL STREAM::SetProperty(int type, ULONG value, ULONG reserved)
292{
293 switch(type) {
294 case PROPERTY_VOLUME:
295 volume = value;
296 break;
297
298 case PROPERTY_BALANCE:
299 balance = value;
300 break;
301
302 case PROPERTY_MASTERVOL:
303 if(mastervol != value) {
304 mastervol = value;
305 return OSS16_SetMasterVol(this, mastervol);
306 }
307 break;
308 default:
309 return FALSE;
310 }
311 return TRUE;
312}
313
314ULONG STREAM::GetProperty(int type)
315{
316 switch(type) {
317 case PROPERTY_FREQUENCY:
318 case PROPERTY_LOOPING:
319 break;
320
321 case PROPERTY_VOLUME:
322 return volume;
323
324 case PROPERTY_BALANCE:
325 return balance;
326
327 case PROPERTY_MASTERVOL:
328 return mastervol;
329 }
330 return -1;
331}
332
333ULONG STREAM::mastervol = MAKE_VOLUME_LR(100, 100);
334
335PSTREAM FindActiveStream(ULONG StreamType)
336{
337 PSTREAM pStream = (PSTREAM) pStreamList->Head();
338
339 while (pStream)
340 if ((pStream->ulStreamType == StreamType) &&
341 (pStream->ulStreamState == STREAM_STREAMING))
342 return pStream;
343 else
344 pStream = (PSTREAM) pStream->pNext;
345
346 return NULL;
347}
348
349PSTREAM FindActiveStream(ULONG StreamType, ULONG StreamId)
350{
351 PSTREAM pStream = (PSTREAM) pStreamList->Head();
352
353 while (pStream)
354 if ((pStream->ulStreamType == StreamType) &&
355 (pStream->ulStreamState == STREAM_STREAMING) && (pStream->ulStreamId == StreamId))
356 return pStream;
357 else
358 pStream = (PSTREAM) pStream->pNext;
359
360 return NULL;
361}
362
363PSTREAM FindStream_fromFile(ULONG ulSysFileNum)
364/* Map a system file handle to a Stream object.
365 * ### FUTURE: Make parm type a real type so we can use overloading,
366 * ### and change name/signature back to "FindStream( fileHandle )".
367 */
368{
369 PSTREAM pStream = (PSTREAM) pStreamList->Head();
370
371 while (pStream)
372 if (pStream->ulSysFileNum == ulSysFileNum)
373 return pStream;
374 else
375 pStream = (PSTREAM) pStream->pNext;
376
377 return NULL;
378}
379
380PSTREAM FindStream(HSTREAM hStream)
381/* Map a stream handle to a Stream object. */
382{
383 PSTREAM pStream = (PSTREAM) pStreamList->Head();
384
385 while (pStream)
386 if (pStream->hstream == hStream)
387 return pStream;
388 else
389 pStream = (PSTREAM) pStream->pNext;
390
391 return NULL;
392}
Note: See TracBrowser for help on using the repository browser.