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

Last change on this file since 148 was 147, checked in by sandervl, 25 years ago

Fixed wave volume, recording gain + wave recording

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1/* $Id: stream.cpp 147 2000-04-24 19:45:21Z 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 if (qhEvent.IsElements()) {
91 PEVENT pnextevent = (PEVENT)qhEvent.Head();
92 ULONG time = GetCurrentTime();
93 ULONG eventtime = pnextevent->GetEventTime();
94 if (eventtime <= time)
95 pnextevent->Report(time);
96 }
97
98}
99ULONG STREAM::EnableEvent(PDDCMDCONTROL pControl)
100{
101
102 // see if the event already exists on the event queue
103 // call FindEvent if we get back an address (event exists)
104 // call the UpdateEvent member function and get the event info updated.
105 // if Findevent returns NULL (no event on queue) then call the construct
106 // a new event and put it on the tail of the event queue. then call
107 // SetNextEvent to update the next event to time out....
108
109 PEVENT pevent = FindEvent(pControl->hEvent, &qhEvent);
110 if (pevent)
111 pevent->UpdateEvent(this,pControl->hEvent,(PCONTROL_PARM)pControl->pParm);
112 else {
113 pevent= new EVENT(this,pControl->hEvent,(PCONTROL_PARM)pControl->pParm);
114 }
115 if (!pevent)
116 return ERROR_TOO_MANY_EVENTS;
117
118 SetNextEvent();
119 return NO_ERROR;
120}
121
122ULONG STREAM::DisableEvent(PDDCMDCONTROL pControl)
123{
124 PEVENT pevent = FindEvent(pControl->hEvent, &qhEvent);
125 if (!pevent)
126 return ERROR_INVALID_EVENT;
127
128 // destroying an event may change things that get referenced in the ISR
129 // so we really need to cli/sti around the call to DestroyElement
130 cli();
131 qhEvent.DestroyElement((PQUEUEELEMENT)pevent);
132 if (qhEvent.Head() != qhEvent.Tail())
133 SetNextEvent();
134 sti();
135 return NO_ERROR;
136}
137
138ULONG STREAM::PauseStreamTime(void)
139{
140 fIncrementCounter = FALSE;
141 return NO_ERROR;
142}
143
144ULONG STREAM::ResumeStreamTime(void)
145{
146
147 fIncrementCounter = TRUE;
148 return NO_ERROR;
149}
150
151
152
153ULONG STREAM::Register(PDDCMDREGISTER p)
154{
155 hstream = p->hStream;
156 pfnSHD = (PFN_SHD) p->pSHDEntryPoint;
157 p->ulAddressType = ADDRESS_TYPE_LINEAR;
158 p->mmtimePerUnit = 0;
159 p->ulBytesPerUnit = 0;
160 p->ulNumBufs = 0x00000010;
161 if (ulStreamType & 0xFFFFFF60) // if this is a midi stream
162 p->ulBufSize = 0x00000200;
163 else
164 p->ulBufSize = 0x00004000;
165 return 0;
166}
167
168
169void STREAM::DeRegister(void)
170{
171 hstream = 0;
172 pfnSHD = NULL;
173}
174
175
176virtual ULONG STREAM::Write(PSTREAMBUF pbuf, unsigned uLength)
177{
178 qhInProcess.PushOnTail((PQUEUEELEMENT)new STREAMBUFFER(uLength, pbuf));
179 return 0;
180}
181
182/**@internal SetNextEvent
183 * @param None
184 * @return None
185 * @notes
186 * the function walks the event list and finds the next event to timeout.
187 * the event is moved to the head of the event queue.
188 *
189 */
190void STREAM::SetNextEvent(void)
191{
192
193 // if there are no events or only one event on the
194 // queue just return
195 if ((qhEvent.Head()) == (qhEvent.Tail()))
196 return;
197
198 PQUEUEELEMENT pele1 = qhEvent.Head();
199 PQUEUEELEMENT pele2 = NULL;
200 ULONG ulTimeToBeat = -1; // -1 equals 0xFFFFFFFF the maximum time
201
202 while (pele1) {
203 if (((PEVENT)pele1)->GetEventTime() <= ulTimeToBeat) {
204 pele2 = pele1;
205 ulTimeToBeat = ((PEVENT)pele1)->GetEventTime();
206 }
207 pele1 = pele1->pNext;
208 }
209 // pele2 should now contain the address of the next
210 // event to time out.. if it is not already on
211 // the head of the Event queue then put it there
212 if (pele2 != qhEvent.Head()) {
213 cli();
214 qhEvent.PopElement(pele2);
215 qhEvent.PushOnHead(pele2);
216 sti();
217 }
218}
219#define INVALID_HSTREAM ((HSTREAM) 0)
220#define INVALID_HFILE ((ULONG) 0)
221
222STREAM::STREAM(ULONG streamtype, USHORT filesysnum)
223{
224 // put this stream on the stream list
225 pStreamList->PushOnTail(this);
226
227 // get the pointer to the hardware object
228 pahw = GetHardwareDevice(streamtype);
229 ulStreamType = streamtype;
230
231 hstream = INVALID_HSTREAM; // We're putting a stream into the stream list, but
232 ulSysFileNum = filesysnum;
233
234 fIncrementCounter = TRUE;
235 ulCurrentTime = 0;
236 ulStreamState = STREAM_STOPPED;
237
238 ulStreamId = 0;
239
240 balance = 50; //middle
241 volume = 80;
242 inputgain = 50;
243 inputsrc = MIX_RECSRC_LINE;
244}
245
246STREAM::~STREAM(void)
247{
248 if (ulStreamState == STREAM_STREAMING)
249 pahw->Stop(this);
250 // detstoy all the STREAMBUFFERs and EVENTs that this STREAM
251 // may still have
252
253 while (qhInProcess.IsElements()) {
254 qhInProcess.DestroyElement(qhInProcess.Head());
255 } /* endwhile */
256
257 while (qhDone.IsElements()) {
258 qhDone.DestroyElement(qhDone.Head());
259 } /* endwhile */
260
261 while (qhEvent.IsElements()) {
262 qhEvent.DestroyElement(qhEvent.Head());
263 } /* endwhile */
264
265 pStreamList->PopElement(this);
266}
267
268void STREAM::SetInputSrc(int src) { inputsrc = src; }
269void STREAM::SetInputGain(ULONG gain) { inputgain = gain; }
270void STREAM::SetVolume(ULONG volume) { this->volume = volume; }
271void STREAM::SetBalance(ULONG balance) { this->balance = balance; }
272
273BOOL STREAM::SetMasterVol(ULONG volume)
274{
275 if(mastervol != volume) {
276 mastervol = volume;
277 return OSS16_SetMasterVol(this, volume);
278 }
279 return TRUE;
280}
281ULONG STREAM::mastervol = MAKE_VOLUME_LR(100, 100);
282
283PSTREAM FindActiveStream(ULONG StreamType)
284{
285 PSTREAM pStream = (PSTREAM) pStreamList->Head();
286
287 while (pStream)
288 if ((pStream->ulStreamType == StreamType) &&
289 (pStream->ulStreamState == STREAM_STREAMING))
290 return pStream;
291 else
292 pStream = (PSTREAM) pStream->pNext;
293
294 return NULL;
295}
296
297PSTREAM FindActiveStream(ULONG StreamType, ULONG StreamId)
298{
299 PSTREAM pStream = (PSTREAM) pStreamList->Head();
300
301 while (pStream)
302 if ((pStream->ulStreamType == StreamType) &&
303 (pStream->ulStreamState == STREAM_STREAMING) && (pStream->ulStreamId == StreamId))
304 return pStream;
305 else
306 pStream = (PSTREAM) pStream->pNext;
307
308 return NULL;
309}
310
311PSTREAM FindStream_fromFile(ULONG ulSysFileNum)
312/* Map a system file handle to a Stream object.
313 * ### FUTURE: Make parm type a real type so we can use overloading,
314 * ### and change name/signature back to "FindStream( fileHandle )".
315 */
316{
317 PSTREAM pStream = (PSTREAM) pStreamList->Head();
318
319 while (pStream)
320 if (pStream->ulSysFileNum == ulSysFileNum)
321 return pStream;
322 else
323 pStream = (PSTREAM) pStream->pNext;
324
325 return NULL;
326}
327
328PSTREAM FindStream(HSTREAM hStream)
329/* Map a stream handle to a Stream object. */
330{
331 PSTREAM pStream = (PSTREAM) pStreamList->Head();
332
333 while (pStream)
334 if (pStream->hstream == hStream)
335 return pStream;
336 else
337 pStream = (PSTREAM) pStream->pNext;
338
339 return NULL;
340}
Note: See TracBrowser for help on using the repository browser.