]> git.saurik.com Git - wxWidgets.git/blame - utils/wxMMedia/snduss.cpp
Fixed refresh bug in wxGLCanvas
[wxWidgets.git] / utils / wxMMedia / snduss.cpp
CommitLineData
4d6306eb
GL
1////////////////////////////////////////////////////////////////////////////////
2// Name: snduss.cpp
3// Purpose: wxMMedia
4// Author: Guilhem Lavaux
5// Created: 1997
6// Updated: 1998
7// Copyright: (C) 1997, 1998, Guilhem Lavaux
8// License: wxWindows license
9////////////////////////////////////////////////////////////////////////////////
10#ifdef __GNUG__
11#pragma implementation "snduss.h"
12#endif
13
14#include <sys/soundcard.h>
15#include <sys/ioctl.h>
16#include <unistd.h>
17#include <fcntl.h>
18#include <time.h>
4d6306eb
GL
19
20#include "wx/app.h"
21#include "wx/utils.h"
22
23#define WXMMEDIA_INTERNAL
24#include "snduss.h"
25#include "sndfrmt.h"
26
27wxUssSound::wxUssSound()
28 : wxSound(),
29 m_srate(0), m_bps(0), m_stereo(0),
30 m_mode(wxSND_OTHER_IO),
31 m_stop_thrd(TRUE), m_sleeping(FALSE)
32{
33 m_fd = -1;
34 m_ussformat.SetCodecNo(WXSOUND_PCM);
35 m_ussformat.SetSign(wxSND_SAMPLE_SIGNED);
36 m_ussformat.SetByteOrder(wxSND_SAMPLE_LE);
37
38 m_sndbuf = new wxStreamBuffer(wxStreamBuffer::read_write);
39 m_sndbuf->Flushable(FALSE);
40 m_sndbuf->Fixed(TRUE);
41}
42
43wxUssSound::~wxUssSound()
44{
45 if (!m_stop_thrd) {
46 m_stop_thrd = TRUE;
47 if (m_sleeping) {
48 m_sleep_mtx.Lock();
49 m_sleep_cond.Signal();
50 m_sleep_mtx.Unlock();
51 }
52 Join();
53 }
54
55 if (m_fd != -1)
56 close(m_fd);
57}
58
59bool wxUssSound::Wakeup(wxSndBuffer& WXUNUSED(buf))
60{
61 printf("Waking up (wxUssSound::Wakeup) ...\n");
62 if (m_stop_thrd) {
63 m_stop_thrd = FALSE;
64 Entry();
65// wxThread::Create();
66 }
67
68 if (m_sleeping) {
69 m_sleep_mtx.Lock();
70 m_sleep_cond.Signal();
71 m_sleep_mtx.Unlock();
72 }
73
74 return TRUE;
75}
76
77void wxUssSound::StopBuffer(wxSndBuffer& buf)
78{
79 buf.HardLock();
80 buf.Set(wxSND_BUFSTOP);
81 buf.HardUnlock();
82 while (buf.IsSet(wxSND_BUFSTOP))
83 wxYield();
84// usleep(0);
85}
86
87void wxUssSound::USS_Sleep()
88{
89 bool ret;
90
91 printf("Asleeping ...\n");
92 m_sleeping = TRUE;
93 m_sleep_mtx.Lock();
94 ret = m_sleep_cond.Wait(m_sleep_mtx, 10, 0);
95 m_sleep_mtx.Unlock();
96 m_sleeping = FALSE;
97
98 printf("Waking up ...\n");
99 if (!ret)
100 m_stop_thrd = TRUE;
101}
102
103bool wxUssSound::DoInput(wxSndBuffer *buf)
104{
105 wxUint32 bufsize;
eb4e516d 106 wxSoundCodec *codec = buf->GetCurrentCodec();
4d6306eb
GL
107
108 m_sndbuf->ResetBuffer();
4d6306eb
GL
109
110 bufsize = codec->Available();
111 if (bufsize > m_max_bufsize)
112 bufsize = m_max_bufsize;
113
114 if (!bufsize) {
115 buf->Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
116 return false;
117 }
eb4e516d 118 read(m_fd, m_sndbuf->GetBufferStart(), bufsize);
4d6306eb
GL
119 codec->Encode();
120
121 return true;
122}
123
124bool wxUssSound::DoOutput(wxSndBuffer *buf)
125{
126 wxSoundCodec *codec = buf->GetCurrentCodec();
127
128 m_sndbuf->ResetBuffer();
4d6306eb
GL
129
130 if (!codec->Available()) {
131 buf->Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
eb4e516d 132 return FALSE;
4d6306eb
GL
133 }
134 codec->Decode();
eb4e516d 135 write(m_fd, m_sndbuf->GetBufferStart(), m_sndbuf->GetIntPosition());
4d6306eb
GL
136
137 // Well ... it's not accurate ! :-|
138 buf->OnBufferOutFinished();
139
eb4e516d
GL
140 return TRUE;
141}
142
143bool wxUssSound::InitBuffer(wxSndBuffer *buf)
144{
145 wxSoundCodec *codec;
146
147 if (!OnSetupDriver(*buf, buf->GetMode())) {
148 if (buf->IsNotSet(wxSND_BUFREADY))
149 return FALSE;
150 }
151
152 codec = buf->GetCurrentCodec();
2a040d3f
GL
153 switch (m_mode) {
154 case wxSND_INPUT:
155 codec->SetInStream(m_sndbuf);
156 codec->InitIO(m_ussformat);
157 codec->InitMode(wxSoundCodec::ENCODING);
158 break;
159 case wxSND_OUTPUT:
160 codec->SetOutStream(m_sndbuf);
161 codec->InitIO(m_ussformat);
162 codec->InitMode(wxSoundCodec::DECODING);
163 break;
164 }
eb4e516d 165 return TRUE;
4d6306eb
GL
166}
167
168void *wxUssSound::Entry()
169{
170 wxNode *node;
171 wxSndBuffer *buf;
172
eb4e516d
GL
173 node = m_buffers.First();
174 if (!node) {
175 m_stop_thrd = FALSE;
176 return NULL;
177 }
178
179 buf = (wxSndBuffer *)node->Data();
180 InitBuffer(buf);
4d6306eb 181
eb4e516d 182 while (!m_stop_thrd) {
4d6306eb
GL
183 buf->HardLock();
184 if (buf->IsSet(wxSND_BUFSTOP)) {
185 buf->HardUnlock();
eb4e516d 186 goto sound_clean_buffer;
4d6306eb
GL
187 }
188 switch(m_mode) {
189 case wxSND_INPUT:
190 if (!DoInput(buf))
eb4e516d 191 goto sound_clean_buffer;
4d6306eb
GL
192 break;
193 case wxSND_OUTPUT:
194 if (!DoOutput(buf))
eb4e516d 195 goto sound_clean_buffer;
4d6306eb
GL
196 break;
197 case wxSND_DUPLEX:
198 case wxSND_OTHER_IO:
eb4e516d 199 goto sound_clean_buffer;
4d6306eb
GL
200 break;
201 }
202 buf->HardUnlock();
eb4e516d
GL
203 continue;
204 sound_clean_buffer:
205 buf->GetCurrentCodec()->ExitMode();
206 delete node;
207 node = m_buffers.First();
208 if (!node)
209 USS_Sleep();
210 if (node)
211 buf = (wxSndBuffer *)node->Data();
4d6306eb
GL
212 }
213 return NULL;
214}
215
216bool wxUssSound::OnSetupDriver(wxSndBuffer& buf, wxSndMode WXUNUSED(mode))
217{
218 wxSoundDataFormat format;
219 wxSoundCodec *codec;
220
eb4e516d 221 codec = buf.GetCurrentCodec();
4d6306eb
GL
222 format = codec->GetPreferredFormat(WXSOUND_PCM);
223
224 if ((format.GetSampleRate() != m_srate) ||
225 (format.GetBps() != m_bps) ||
226 (format.GetStereo() != m_stereo)) {
227
228 if (!SetupSound(format.GetSampleRate(), format.GetBps(),
229 format.GetStereo())) {
230 m_buffers.DeleteObject(&buf);
231 buf.Clear(wxSND_BUFLOCKED | wxSND_BUFREADY);
232 buf.SetError(wxSND_CANTSET);
eb4e516d 233 return FALSE;
4d6306eb
GL
234 }
235 m_mode = wxSND_OTHER_IO;
236 }
237
238 if (buf.GetMode() != m_mode) {
239 m_mode = buf.GetMode();
eb4e516d 240 return FALSE;
4d6306eb
GL
241 }
242
eb4e516d 243 return TRUE;
4d6306eb
GL
244}
245
246wxUint32 wxUssSound::GetNbFragments()
247{
248 struct audio_buf_info frag_info;
249
250 ioctl(m_fd, SNDCTL_DSP_GETOSPACE, &frag_info);
251
252 return frag_info.fragstotal;
253}
254
255wxUint32 wxUssSound::GetFragmentSize()
256{
257 return m_max_bufsize;
258}
259
260bool wxUssSound::SetupSound(wxUint16 srate, wxUint8 bps, bool stereo)
261{
262 int tmp;
263 unsigned long tmp_ul;
264
265 if (m_fd != -1) {
266 delete m_sndbuf;
267 fsync(m_fd);
268 close(m_fd);
269 }
270
271 m_fd = open("/dev/dsp", O_RDWR);
272
273 tmp = stereo;
274 if (ioctl(m_fd, SNDCTL_DSP_STEREO, &tmp) < 0)
275 return FALSE;
276 m_stereo = tmp;
277
278 tmp_ul = srate;
279 if (ioctl(m_fd, SNDCTL_DSP_SPEED, &tmp_ul) < 0)
280 return FALSE;
281 m_srate = tmp_ul;
282
283 tmp = bps;
284 if (ioctl(m_fd, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
285 return FALSE;
286 m_bps = tmp;
287
288 ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &tmp);
289 m_max_bufsize = tmp;
290 m_sndbuf->SetBufferIO(m_max_bufsize);
291
292 m_ussformat.SetBps(m_bps);
293 m_ussformat.SetChannels((m_stereo) ? 2 : 1);
294 m_ussformat.SetSampleRate(m_srate);
295
296 return TRUE;
297}