source: cmedia/trunk/Drv16/stream.cpp

Last change on this file was 553, checked in by rudi, 14 years ago

Adapt sourcecode to OpenWatcom

File size: 11.5 KB
Line 
1/* $Id: stream.cpp,v 1.5 2001/05/09 17:44:24 sandervl Exp $ */
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 "ioctl.h"
36
37#include <ossidc.h>
38
39#include <dbgos2.h>
40
41
42
43
44PQUEUEHEAD pStreamList; // List head for Streams. Initialized during DD initilialization.
45
46void STREAM::ReturnBuffer(void)
47{
48 SHD_REPORTINT shdri; // structure used to return buffers to SHD
49 PSTREAMBUFFER temp = (PSTREAMBUFFER)qhDone.PopHead();
50
51 if (temp)
52 {
53 shdri.ulFunction = SHD_REPORT_INT;
54
55 // if this is a write (playback) then set the streamtype and
56 // tell the stream handler that we played all of the buffer.
57 if (usStreamType & STREAM_WRITE) {
58 shdri.ulFlag = SHD_WRITE_COMPLETE;
59 shdri.ulStatus = temp->ulBuffsz;
60 }
61 // if this is a capture then tell the stream hamdler
62 // how much data we wrote to the buffer
63 else {
64 shdri.ulFlag = SHD_READ_COMPLETE;
65 shdri.ulStatus = temp->ulBuffpos;
66 }
67 shdri.hStream = hstream;
68 shdri.pBuffer = temp->pBuffptr;
69 shdri.ulStreamTime = GetCurrentTime();
70 pfnSHD(&shdri);
71 delete temp;
72 }
73}
74
75//
76// ReturnBuffers(void)
77// Return all buffers to MMPM.
78//
79void STREAM::ReturnBuffers(void)
80{
81 // move all buffers from the InProcess Queue to the Done Queue
82 while (qhInProcess.IsElements()) {
83 qhDone.PushOnTail(qhInProcess.PopHead());
84 }
85 // Return all the buffers on the Done Queue
86 while (qhDone.IsElements()) {
87#ifdef DEBUG
88 PSTREAMBUFFER ptemp = (PSTREAMBUFFER)qhDone.Head();
89 dprintf(("Return buffer %lx size %d", ptemp->pBuffptr, ptemp->ulBuffsz));
90#endif
91 ReturnBuffer();
92 }
93}
94//
95// ProcessEvents
96// called by the Process at interrupt time to see if there are
97// any events that have timed out
98//
99void STREAM::ProcessEvents(void)
100{
101//SvL: BUGFIX: check all events
102#if 1
103 if (qhEvent.IsElements()) {
104 PEVENT pnextevent = (PEVENT)qhEvent.Head();
105 ULONG time = GetCurrentTime();
106 while(pnextevent) {
107 ULONG eventtime = pnextevent->GetEventTime();
108 if (eventtime <= time)
109 pnextevent->Report(time);
110 pnextevent = (PEVENT)pnextevent->pNext;
111 }
112 }
113#else
114 if (qhEvent.IsElements()) {
115 PEVENT pnextevent = (PEVENT)qhEvent.Head();
116 ULONG time = GetCurrentTime();
117 ULONG eventtime = pnextevent->GetEventTime();
118 if (eventtime <= time)
119 pnextevent->Report(time);
120 }
121#endif
122}
123
124ULONG STREAM::EnableEvent(PDDCMDCONTROL pControl)
125{
126
127 // see if the event already exists on the event queue
128 // call FindEvent if we get back an address (event exists)
129 // call the UpdateEvent member function and get the event info updated.
130 // if Findevent returns NULL (no event on queue) then call the construct
131 // a new event and put it on the tail of the event queue. then call
132 // SetNextEvent to update the next event to time out....
133
134 PEVENT pevent = FindEvent(pControl->hEvent, &qhEvent);
135 if (pevent)
136 pevent->UpdateEvent(this,pControl->hEvent,(PCONTROL_PARM)pControl->pParm);
137 else {
138 pevent= new EVENT(this,pControl->hEvent,(PCONTROL_PARM)pControl->pParm);
139 }
140 if (!pevent)
141 return ERROR_TOO_MANY_EVENTS;
142
143 SetNextEvent();
144 return NO_ERROR;
145}
146
147ULONG STREAM::DisableEvent(PDDCMDCONTROL pControl)
148{
149 PEVENT pevent = FindEvent(pControl->hEvent, &qhEvent);
150 if (!pevent)
151 return ERROR_INVALID_EVENT;
152
153 // destroying an event may change things that get referenced in the ISR
154 // so we really need to cli/sti around the call to DestroyElement
155 cli();
156 qhEvent.DestroyElement((PQUEUEELEMENT)pevent);
157 if (qhEvent.Head() != qhEvent.Tail())
158 SetNextEvent();
159 sti();
160 return NO_ERROR;
161}
162
163ULONG STREAM::PauseStreamTime(void)
164{
165 fIncrementCounter = FALSE;
166 return NO_ERROR;
167}
168
169ULONG STREAM::ResumeStreamTime(void)
170{
171
172 fIncrementCounter = TRUE;
173 return NO_ERROR;
174}
175
176
177
178ULONG STREAM::Register(PDDCMDREGISTER p)
179{
180 hstream = p->hStream;
181 pfnSHD = (PFN_SHD) p->pSHDEntryPoint;
182
183 p->mmtimePerUnit = 0;
184 p->ulBytesPerUnit = 0;
185 p->ulNumBufs = 16;
186 p->ulBufSize = 512;
187 p->ulAddressType = ADDRESS_TYPE_VIRTUAL;
188
189 return 0;
190}
191
192
193void STREAM::DeRegister(void)
194{
195 hstream = 0;
196 pfnSHD = NULL;
197}
198
199
200#pragma off (unreferenced)
201ULONG STREAM::Write(PSTREAMBUF pbuf, ULONG uLength, BOOL fLooping)
202#pragma on (unreferenced)
203{
204 qhInProcess.PushOnTail((PQUEUEELEMENT)new STREAMBUFFER(uLength, pbuf));
205 return 0;
206}
207
208/**@internal SetNextEvent
209 * @param None
210 * @return None
211 * @notes
212 * the function walks the event list and finds the next event to timeout.
213 * the event is moved to the head of the event queue.
214 *
215 */
216void STREAM::SetNextEvent(void)
217{
218
219 // if there are no events or only one event on the
220 // queue just return
221 if ((qhEvent.Head()) == (qhEvent.Tail()))
222 return;
223
224 PQUEUEELEMENT pele1 = qhEvent.Head();
225 PQUEUEELEMENT pele2 = NULL;
226 ULONG ulTimeToBeat = -1; // -1 equals 0xFFFFFFFF the maximum time
227
228 while (pele1) {
229 if (((PEVENT)pele1)->GetEventTime() <= ulTimeToBeat) {
230 pele2 = pele1;
231 ulTimeToBeat = ((PEVENT)pele1)->GetEventTime();
232 }
233 pele1 = pele1->pNext;
234 }
235 // pele2 should now contain the address of the next
236 // event to time out.. if it is not already on
237 // the head of the Event queue then put it there
238 if (pele2 != qhEvent.Head()) {
239 cli();
240 qhEvent.PopElement(pele2);
241 qhEvent.PushOnHead(pele2);
242 sti();
243 }
244}
245#define INVALID_HSTREAM ((HSTREAM) 0)
246#define INVALID_HFILE ((ULONG) 0)
247
248STREAM::STREAM(USHORT streamtype, USHORT filesysnum)
249{
250 // put this stream on the stream list
251 pStreamList->PushOnTail(this);
252
253 // get the pointer to the hardware object
254 pahw = GetHardwareDevice(streamtype);
255 usStreamType = streamtype;
256
257 hstream = INVALID_HSTREAM; // We're putting a stream into the stream list, but
258 usSysFileNum = filesysnum;
259
260 fIncrementCounter = TRUE;
261 ulCurrentTime = 0;
262 usStreamState = STREAM_STOPPED;
263
264 ulStreamId = 0;
265
266 volume = 100; // full
267 balance = 50; // middle
268 inputgain = 50; // moderate
269 inputsrc = MIX_RECSRC_LINE;
270}
271
272STREAM::~STREAM(void)
273{
274 if (usStreamState == STREAM_STREAMING)
275 pahw->Stop(this);
276 // detstoy all the STREAMBUFFERs and EVENTs that this STREAM
277 // may still have
278
279 while (qhInProcess.IsElements()) {
280 qhInProcess.DestroyElement(qhInProcess.Head());
281 } /* endwhile */
282
283 while (qhDone.IsElements()) {
284 qhDone.DestroyElement(qhDone.Head());
285 } /* endwhile */
286
287 while (qhEvent.IsElements()) {
288 qhEvent.DestroyElement(qhEvent.Head());
289 } /* endwhile */
290
291 pStreamList->PopElement(this);
292}
293
294void STREAM::SetLooping(BOOL /*fLooping*/)
295{
296 return;
297}
298
299BOOL STREAM::SetProperty(int type, ULONG value, ULONG /*reserved*/)
300{
301 switch(type) {
302 case PROPERTY_VOLUME:
303 if( volume != value ) {
304 volume = value; mixerchange = TRUE;
305 }
306 break;
307
308 case PROPERTY_BALANCE:
309 if( balance != value ) {
310 balance = value; mixerchange = TRUE;
311 }
312 break;
313
314 case PROPERTY_MASTERVOL:
315/* if( mastervol != value ) {
316 mastervol = value; mixerchange = TRUE;
317 return OSS16_SetMasterVol(this, mastervol);
318 }
319*/
320 SetMasterControl(value, (ULONG)-1);
321 break;
322
323 default:
324 return FALSE;
325 }
326
327 return TRUE;
328}
329
330ULONG STREAM::GetProperty(int type)
331{
332 switch(type) {
333 case PROPERTY_VOLUME:
334 return volume;
335
336 case PROPERTY_BALANCE:
337 return balance;
338
339 case PROPERTY_MASTERVOL:
340 return mastervol;
341/*
342 case PROPERTY_MASTERBAL:
343 return masterbal;
344
345 case PROPERTY_FREQUENCY:
346 case PROPERTY_LOOPING:
347 break;
348*/
349 }
350
351 return -1;
352}
353
354
355void STREAM::SetMasterControl(ULONG ulMasterVol, ULONG ulMasterBal)
356{
357 ULONG l, r;
358 USHORT ctChange = 0;
359
360 if( ulMasterVol != (ULONG)-1 && ulMasterVol != mastervol ) {
361 mastervol = ulMasterVol; ctChange++;
362 }
363
364 if( ulMasterBal != (ULONG)-1 && ulMasterBal != masterbal ) {
365 masterbal = ulMasterBal; ctChange++;
366 }
367
368 if( ctChange ) {
369 l = (GET_VOLUME_L(mastervol) * GET_VOLUME_L(masterbal)) / 100;
370 r = (GET_VOLUME_R(mastervol) * GET_VOLUME_R(masterbal)) / 100;
371
372 mixerchange |=
373 OSS16_SetGlobalVol(0, MIX_SETMASTERVOL, MAKE_VOLUME_LR(l, r));
374 }
375}
376
377
378ULONG STREAM::mastervol = MAKE_VOLUME_LR(100, 100);
379ULONG STREAM::masterbal = MAKE_VOLUME_LR(100, 100);
380BOOL STREAM::mixerchange = FALSE;
381
382
383
384
385PSTREAM FindActiveStream(USHORT StreamType)
386{
387 PSTREAM pStream = (PSTREAM) pStreamList->Head();
388
389 while (pStream)
390 if ((pStream->usStreamType == StreamType) &&
391 (pStream->usStreamState == STREAM_STREAMING))
392 return pStream;
393 else
394 pStream = (PSTREAM) pStream->pNext;
395
396 return NULL;
397}
398
399PSTREAM FindActiveStream(USHORT StreamType, ULONG StreamId)
400{
401 PSTREAM pStream = (PSTREAM) pStreamList->Head();
402
403 while (pStream)
404 if ((pStream->usStreamType == StreamType) &&
405 (pStream->usStreamState == STREAM_STREAMING) && (pStream->ulStreamId == StreamId))
406 return pStream;
407 else
408 pStream = (PSTREAM) pStream->pNext;
409
410 return NULL;
411}
412
413PSTREAM FindStream_fromFile(USHORT usSysFileNum)
414/* Map a system file handle to a Stream object.
415 * ### FUTURE: Make parm type a real type so we can use overloading,
416 * ### and change name/signature back to "FindStream( fileHandle )".
417 */
418{
419 PSTREAM pStream = (PSTREAM) pStreamList->Head();
420
421 while (pStream)
422 if (pStream->usSysFileNum == usSysFileNum)
423 return pStream;
424 else
425 pStream = (PSTREAM) pStream->pNext;
426
427 return NULL;
428}
429
430PSTREAM FindStream(HSTREAM hStream)
431/* Map a stream handle to a Stream object. */
432{
433 PSTREAM pStream = (PSTREAM) pStreamList->Head();
434
435 while (pStream)
436 if (pStream->hstream == hStream)
437 return pStream;
438 else
439 pStream = (PSTREAM) pStream->pNext;
440
441 return NULL;
442}
443
444// Rudi: enumerate stream list
445PSTREAM EnumStreams(PSTREAM pStream, USHORT StreamType)
446{
447 pStream = ( pStream ) ?
448 (PSTREAM) pStream->pNext : (PSTREAM) pStreamList->Head();
449
450 while( pStream )
451 if( StreamType == STREAM_ANY || StreamType == pStream->usStreamType )
452 return pStream;
453 else
454 pStream = (PSTREAM) pStream->pNext;
455
456 return NULL;
457}
458
Note: See TracBrowser for help on using the repository browser.