summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/audiodevice.cpp
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/audiodevice.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/audiodevice.cpp155
1 files changed, 69 insertions, 86 deletions
diff --git a/core/multimedia/opieplayer/audiodevice.cpp b/core/multimedia/opieplayer/audiodevice.cpp
index 7b3700a..9a10eb4 100644
--- a/core/multimedia/opieplayer/audiodevice.cpp
+++ b/core/multimedia/opieplayer/audiodevice.cpp
@@ -1,10 +1,10 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
@@ -14,14 +14,16 @@
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20// L.J.Potter added better error code Fri 02-15-2002 14:37:47
20 21
21#include <stdlib.h> 22#include <stdlib.h>
23#include <stdio.h>
22#include <qpe/qpeapplication.h> 24#include <qpe/qpeapplication.h>
23#include <qpe/config.h> 25#include <qpe/config.h>
24#include "audiodevice.h" 26#include "audiodevice.h"
25 27
26#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP) 28#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP)
27#include "qpe/qcopenvelope_qws.h" 29#include "qpe/qcopenvelope_qws.h"
@@ -103,39 +105,40 @@ void AudioDevice::getVolume( unsigned int& leftVolume, unsigned int& rightVolume
103 formatData.nBlockAlign = 4; 105 formatData.nBlockAlign = 4;
104 formatData.nChannels = 2; 106 formatData.nChannels = 2;
105 formatData.nSamplesPerSec = 44000; 107 formatData.nSamplesPerSec = 44000;
106 formatData.wBitsPerSample = 16; 108 formatData.wBitsPerSample = 16;
107 waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL); 109 waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL);
108 if ( waveOutGetVolume( handle, (LPDWORD)&volume ) ) 110 if ( waveOutGetVolume( handle, (LPDWORD)&volume ) )
109 qDebug( "get volume of audio device failed" ); 111// qDebug( "get volume of audio device failed" );
110 waveOutClose( handle ); 112 waveOutClose( handle );
111 leftVolume = volume & 0xFFFF; 113 leftVolume = volume & 0xFFFF;
112 rightVolume = volume >> 16; 114 rightVolume = volume >> 16;
113#else 115#else
114 int mixerHandle = open( "/dev/mixer", O_RDWR ); 116 int mixerHandle = open( "/dev/mixer", O_RDWR );
115 if ( mixerHandle >= 0 ) { 117 if ( mixerHandle >= 0 ) {
116 ioctl( mixerHandle, MIXER_READ(0), &volume ); 118 if(ioctl( mixerHandle, MIXER_READ(0), &volume )==-1)
119 perror("ioctl(\"MIXER_READ\")");
117 close( mixerHandle ); 120 close( mixerHandle );
118 } else 121 } else
119 qDebug( "get volume of audio device failed" ); 122 perror("open(\"/dev/mixer\")");
120 leftVolume = ((volume & 0x00FF) << 16) / 101; 123 leftVolume = ((volume & 0x00FF) << 16) / 101;
121 rightVolume = ((volume & 0xFF00) << 8) / 101; 124 rightVolume = ((volume & 0xFF00) << 8) / 101;
122#endif 125#endif
123} 126}
124 127
125 128
126void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume, bool muted ) { 129void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume, bool muted ) {
127 AudioDevicePrivate::muted = muted; 130 AudioDevicePrivate::muted = muted;
128 if ( muted ) { 131 if ( muted ) {
129 AudioDevicePrivate::leftVolume = leftVolume; 132 AudioDevicePrivate::leftVolume = leftVolume;
130 AudioDevicePrivate::rightVolume = rightVolume; 133 AudioDevicePrivate::rightVolume = rightVolume;
131 leftVolume = 0; 134 leftVolume = 0;
132 rightVolume = 0; 135 rightVolume = 0;
133 } else { 136 } else {
134 leftVolume = ( (int) leftVolume < 0 ) ? 0 : (( leftVolume > 0xFFFF ) ? 0xFFFF : leftVolume ); 137 leftVolume = ( (int) leftVolume < 0 ) ? 0 : (( leftVolume > 0xFFFF ) ? 0xFFFF : leftVolume );
135 rightVolume = ( (int)rightVolume < 0 ) ? 0 : (( rightVolume > 0xFFFF ) ? 0xFFFF : rightVolume ); 138 rightVolume = ( (int)rightVolume < 0 ) ? 0 : (( rightVolume > 0xFFFF ) ? 0xFFFF : rightVolume );
136 } 139 }
137#ifdef Q_OS_WIN32 140#ifdef Q_OS_WIN32
138 HWAVEOUT handle; 141 HWAVEOUT handle;
139 WAVEFORMATEX formatData; 142 WAVEFORMATEX formatData;
140 formatData.cbSize = sizeof(WAVEFORMATEX); 143 formatData.cbSize = sizeof(WAVEFORMATEX);
141 formatData.wFormatTag = WAVE_FORMAT_PCM; 144 formatData.wFormatTag = WAVE_FORMAT_PCM;
@@ -144,27 +147,29 @@ void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume,
144 formatData.nChannels = 2; 147 formatData.nChannels = 2;
145 formatData.nSamplesPerSec = 44000; 148 formatData.nSamplesPerSec = 44000;
146 formatData.wBitsPerSample = 16; 149 formatData.wBitsPerSample = 16;
147 waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL); 150 waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL);
148 unsigned int volume = (rightVolume << 16) | leftVolume; 151 unsigned int volume = (rightVolume << 16) | leftVolume;
149 if ( waveOutSetVolume( handle, volume ) ) 152 if ( waveOutSetVolume( handle, volume ) )
150 qDebug( "set volume of audio device failed" ); 153// qDebug( "set volume of audio device failed" );
151 waveOutClose( handle ); 154 waveOutClose( handle );
152#else 155#else
153 // Volume can be from 0 to 100 which is 101 distinct values 156 // Volume can be from 0 to 100 which is 101 distinct values
154 unsigned int rV = (rightVolume * 101) >> 16; 157 unsigned int rV = (rightVolume * 101) >> 16;
155 158
156# if 0 159# if 0
157 unsigned int lV = (leftVolume * 101) >> 16; 160 unsigned int lV = (leftVolume * 101) >> 16;
158 unsigned int volume = ((rV << 8) & 0xFF00) | (lV & 0x00FF); 161 unsigned int volume = ((rV << 8) & 0xFF00) | (lV & 0x00FF);
159 int mixerHandle = 0; 162 int mixerHandle = 0;
160 if ( ( mixerHandle = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { 163 if ( ( mixerHandle = open( "/dev/mixer", O_RDWR ) ) >= 0 ) {
161 ioctl( mixerHandle, MIXER_WRITE(0), &volume ); 164 if(ioctl( mixerHandle, MIXER_WRITE(0), &volume ) ==-1)
165 perror("ioctl(\"MIXER_WRITE\")");
162 close( mixerHandle ); 166 close( mixerHandle );
163 } else 167 } else
164 qDebug( "set volume of audio device failed" ); 168 perror("open(\"/dev/mixer\")");
169
165# else 170# else
166 // This is the way this has to be done now I guess, doesn't allow for 171 // This is the way this has to be done now I guess, doesn't allow for
167 // independant right and left channel setting, or setting for different outputs 172 // independant right and left channel setting, or setting for different outputs
168 Config cfg("Sound"); 173 Config cfg("Sound");
169 cfg.setGroup("System"); 174 cfg.setGroup("System");
170 cfg.writeEntry("Volume",(int)rV); 175 cfg.writeEntry("Volume",(int)rV);
@@ -183,97 +188,75 @@ void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume,
183 188
184AudioDevice::AudioDevice( unsigned int f, unsigned int chs, unsigned int bps ) { 189AudioDevice::AudioDevice( unsigned int f, unsigned int chs, unsigned int bps ) {
185 d = new AudioDevicePrivate; 190 d = new AudioDevicePrivate;
186 d->frequency = f; 191 d->frequency = f;
187 d->channels = chs; 192 d->channels = chs;
188 d->bytesPerSample = bps; 193 d->bytesPerSample = bps;
194// qDebug("%d",bps);
195 int format=0;
196 if( bps == 8) format = AFMT_U8;
197 else if( bps <= 0) format = AFMT_S16_LE;
198 else format = AFMT_S16_LE;
189 199
200// qDebug("AD- freq %d, channels %d, b/sample %d, bitrate %d",f,chs,bps,format);
190 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) ); 201 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) );
191 202
192#ifdef Q_OS_WIN32
193 UINT result;
194 WAVEFORMATEX formatData;
195 formatData.cbSize = sizeof(WAVEFORMATEX);
196/*
197 // Other possible formats windows supports
198 formatData.wFormatTag = WAVE_FORMAT_MPEG;
199 formatData.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
200 formatData.wFormatTag = WAVE_FORMAT_ADPCM;
201*/
202 formatData.wFormatTag = WAVE_FORMAT_PCM;
203 formatData.nAvgBytesPerSec = bps * chs * f;
204 formatData.nBlockAlign = bps * chs;
205 formatData.nChannels = chs;
206 formatData.nSamplesPerSec = f;
207 formatData.wBitsPerSample = bps * 8;
208 // Open a waveform device for output
209 if (result = waveOutOpen((LPHWAVEOUT)&d->handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL)) {
210 QString errorMsg = "error opening audio device.\nReason: %i - ";
211 switch (result) {
212 case MMSYSERR_ALLOCATED:errorMsg += "Specified resource is already allocated."; break;
213 case MMSYSERR_BADDEVICEID:errorMsg += "Specified device identifier is out of range."; break;
214 case MMSYSERR_NODRIVER:errorMsg += "No device driver is present."; break;
215 case MMSYSERR_NOMEM:errorMsg += "Unable to allocate or lock memory."; break;
216 case WAVERR_BADFORMAT:errorMsg += "Attempted to open with an unsupported waveform-audio format."; break;
217 case WAVERR_SYNC: errorMsg += "The device is synchronous but waveOutOpen was called without using the WAVE_ALLOWSYNC flag."; break;
218 default: errorMsg += "Undefined error"; break;
219 }
220 qDebug( errorMsg, result );
221 }
222
223 d->bufferSize = sound_fragment_bytes;
224#else
225 203
226 int fragments = 0x10000 * 8 + sound_fragment_shift; 204 int fragments = 0x10000 * 8 + sound_fragment_shift;
227 int format = AFMT_S16_LE;
228 int capabilities = 0; 205 int capabilities = 0;
229 206
230#ifdef KEEP_DEVICE_OPEN 207#ifdef KEEP_DEVICE_OPEN
231 if ( AudioDevicePrivate::dspFd == 0 ) { 208 if ( AudioDevicePrivate::dspFd == 0 ) {
232#endif 209#endif
233 if ( ( d->handle = ::open( "/dev/dsp", O_WRONLY ) ) < 0 ) { 210 if ( ( d->handle = ::open( "/dev/dsp", O_WRONLY ) ) < 0 ) {
234 qDebug( "error opening audio device /dev/dsp, sending data to /dev/null instead" ); 211 perror("open(\"/dev/dsp\") sending to /dev/null instead");
235 d->handle = ::open( "/dev/null", O_WRONLY ); 212 d->handle = ::open( "/dev/null", O_WRONLY );
236 } 213 }
237#ifdef KEEP_DEVICE_OPEN 214#ifdef KEEP_DEVICE_OPEN
238 AudioDevicePrivate::dspFd = d->handle; 215 AudioDevicePrivate::dspFd = d->handle;
239 } else { 216 } else {
240 d->handle = AudioDevicePrivate::dspFd; 217 d->handle = AudioDevicePrivate::dspFd;
241 } 218 }
242#endif 219#endif
243 220
244 ioctl( d->handle, SNDCTL_DSP_GETCAPS, &capabilities ); 221 if(ioctl( d->handle, SNDCTL_DSP_GETCAPS, &capabilities )==-1)
245 ioctl( d->handle, SNDCTL_DSP_SETFRAGMENT, &fragments ); 222 perror("ioctl(\"SNDCTL_DSP_GETCAPS\")");
246 ioctl( d->handle, SNDCTL_DSP_SETFMT, &format ); 223 if(ioctl( d->handle, SNDCTL_DSP_SETFRAGMENT, &fragments )==-1)
247 ioctl( d->handle, SNDCTL_DSP_SPEED, &d->frequency ); 224 perror("ioctl(\"SNDCTL_DSP_SETFRAGMENT\")");
225 if(ioctl( d->handle, SNDCTL_DSP_SETFMT, & format )==-1)
226 perror("ioctl(\"SNDCTL_DSP_SETFMT\")");
227 qDebug("freq %d", d->frequency);
228 if(ioctl( d->handle, SNDCTL_DSP_SPEED, &d->frequency )==-1)
229 perror("ioctl(\"SNDCTL_DSP_SPEED\")");
230 qDebug("channels %d",d->channels);
248 if ( ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ) == -1 ) { 231 if ( ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ) == -1 ) {
249 d->channels = ( d->channels == 1 ) ? 2 : d->channels; 232 d->channels = ( d->channels == 1 ) ? 2 : d->channels;
250 ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ); 233 if(ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels )==-1)
234 perror("ioctl(\"SNDCTL_DSP_CHANNELS\")");
251 } 235 }
252 236
253 d->bufferSize = sound_fragment_bytes; 237 d->bufferSize = sound_fragment_bytes;
254 d->unwrittenBuffer = new char[d->bufferSize]; 238 d->unwrittenBuffer = new char[d->bufferSize];
255 d->unwritten = 0; 239 d->unwritten = 0;
256 d->can_GETOSPACE = TRUE; // until we find otherwise 240 d->can_GETOSPACE = TRUE; // until we find otherwise
257 241
258 //if ( chs != d->channels ) qDebug( "Wanted %d, got %d channels", chs, d->channels ); 242 //if ( chs != d->channels ) qDebug( "Wanted %d, got %d channels", chs, d->channels );
259 //if ( f != d->frequency ) qDebug( "wanted %dHz, got %dHz", f, d->frequency ); 243 //if ( f != d->frequency ) qDebug( "wanted %dHz, got %dHz", f, d->frequency );
260 //if ( capabilities & DSP_CAP_BATCH ) qDebug( "Sound card has local buffer" ); 244 //if ( capabilities & DSP_CAP_BATCH ) qDebug( "Sound card has local buffer" );
261 //if ( capabilities & DSP_CAP_REALTIME )qDebug( "Sound card has realtime sync" ); 245 //if ( capabilities & DSP_CAP_REALTIME )qDebug( "Sound card has realtime sync" );
262 //if ( capabilities & DSP_CAP_TRIGGER ) qDebug( "Sound card has precise trigger" ); 246 //if ( capabilities & DSP_CAP_TRIGGER ) qDebug( "Sound card has precise trigger" );
263 //if ( capabilities & DSP_CAP_MMAP ) qDebug( "Sound card can mmap" ); 247 //if ( capabilities & DSP_CAP_MMAP ) qDebug( "Sound card can mmap" );
264#endif
265} 248}
266 249
267 250
268AudioDevice::~AudioDevice() { 251AudioDevice::~AudioDevice() {
269#ifdef Q_OS_WIN32 252#ifdef Q_OS_WIN32
270 waveOutClose( (HWAVEOUT)d->handle ); 253 waveOutClose( (HWAVEOUT)d->handle );
271#else 254#else
272# ifndef KEEP_DEVICE_OPEN 255# ifndef KEEP_DEVICE_OPEN
273 close( d->handle ); // Now it should be safe to shut the handle 256 close( d->handle ); // Now it should be safe to shut the handle
274# endif 257# endif
275 delete d->unwrittenBuffer; 258 delete d->unwrittenBuffer;
276 delete d; 259 delete d;
277#endif 260#endif
278} 261}
279 262
@@ -294,21 +277,21 @@ void AudioDevice::write( char *buffer, unsigned int length )
294 lpWaveHdr->dwBufferLength = length; 277 lpWaveHdr->dwBufferLength = length;
295 lpWaveHdr->dwFlags = 0L; 278 lpWaveHdr->dwFlags = 0L;
296 lpWaveHdr->dwLoops = 0L; 279 lpWaveHdr->dwLoops = 0L;
297 waveOutPrepareHeader( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) ); 280 waveOutPrepareHeader( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) );
298 // waveOutWrite returns immediately. the data is sent in the background. 281 // waveOutWrite returns immediately. the data is sent in the background.
299 if ( waveOutWrite( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) ) ) 282 if ( waveOutWrite( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) ) )
300 qDebug( "failed to write block to audio device" ); 283 qDebug( "failed to write block to audio device" );
301 // emit completedIO(); 284 // emit completedIO();
302#else 285#else
303 int t = ::write( d->handle, buffer, length ); 286 int t = ::write( d->handle, buffer, length );
304 if ( t<0 ) t = 0; 287 if ( t<0 ) t = 0;
305 if ( t != (int)length) { 288 if ( t != (int)length) {
306 qDebug("Ahhh!! memcpys 1"); 289 qDebug("Ahhh!! memcpys 1");
307 memcpy(d->unwrittenBuffer,buffer+t,length-t); 290 memcpy(d->unwrittenBuffer,buffer+t,length-t);
308 d->unwritten = length-t; 291 d->unwritten = length-t;
309 } 292 }
310#endif 293#endif
311} 294}
312 295
313 296
314unsigned int AudioDevice::channels() const 297unsigned int AudioDevice::channels() const
@@ -338,50 +321,50 @@ unsigned int AudioDevice::canWrite() const
338{ 321{
339#ifdef Q_OS_WIN32 322#ifdef Q_OS_WIN32
340 return bufferSize(); // Any better? 323 return bufferSize(); // Any better?
341#else 324#else
342 audio_buf_info info; 325 audio_buf_info info;
343 if ( d->can_GETOSPACE && ioctl(d->handle,SNDCTL_DSP_GETOSPACE,&info) ) { 326 if ( d->can_GETOSPACE && ioctl(d->handle,SNDCTL_DSP_GETOSPACE,&info) ) {
344 d->can_GETOSPACE = FALSE; 327 d->can_GETOSPACE = FALSE;
345 fcntl( d->handle, F_SETFL, O_NONBLOCK ); 328 fcntl( d->handle, F_SETFL, O_NONBLOCK );
346 } 329 }
347 if ( d->can_GETOSPACE ) { 330 if ( d->can_GETOSPACE ) {
348 int t = info.fragments * sound_fragment_bytes; 331 int t = info.fragments * sound_fragment_bytes;
349 return QMIN(t,(int)bufferSize()); 332 return QMIN(t,(int)bufferSize());
350 } else { 333 } else {
351 if ( d->unwritten ) { 334 if ( d->unwritten ) {
352 int t = ::write( d->handle, d->unwrittenBuffer, d->unwritten ); 335 int t = ::write( d->handle, d->unwrittenBuffer, d->unwritten );
353 if ( t<0 ) t = 0; 336 if ( t<0 ) t = 0;
354 if ( (unsigned)t!=d->unwritten ) { 337 if ( (unsigned)t!=d->unwritten ) {
355 memcpy(d->unwrittenBuffer,d->unwrittenBuffer+t,d->unwritten-t); 338 memcpy(d->unwrittenBuffer,d->unwrittenBuffer+t,d->unwritten-t);
356 d->unwritten -= t; 339 d->unwritten -= t;
357 } else { 340 } else {
358 d->unwritten = 0; 341 d->unwritten = 0;
359 } 342 }
360 } 343 }
361 if ( d->unwritten ) 344 if ( d->unwritten )
362 return 0; 345 return 0;
363 else 346 else
364 return d->bufferSize; 347 return d->bufferSize;
365 } 348 }
366#endif 349#endif
367} 350}
368 351
369 352
370int AudioDevice::bytesWritten() { 353int AudioDevice::bytesWritten() {
371#ifdef Q_OS_WIN32 354#ifdef Q_OS_WIN32
372 MMTIME pmmt = { TIME_BYTES, 0 }; 355 MMTIME pmmt = { TIME_BYTES, 0 };
373 if ( ( waveOutGetPosition( (HWAVEOUT)d->handle, &pmmt, sizeof(MMTIME) ) != MMSYSERR_NOERROR ) || ( pmmt.wType != TIME_BYTES ) ) { 356 if ( ( waveOutGetPosition( (HWAVEOUT)d->handle, &pmmt, sizeof(MMTIME) ) != MMSYSERR_NOERROR ) || ( pmmt.wType != TIME_BYTES ) ) {
374 qDebug( "failed to get audio device position" ); 357 qDebug( "failed to get audio device position" );
375 return -1; 358 return -1;
376 } 359 }
377 return pmmt.u.cb; 360 return pmmt.u.cb;
378#else 361#else
379 int buffered = 0; 362 int buffered = 0;
380 if ( ioctl( d->handle, SNDCTL_DSP_GETODELAY, &buffered ) ) { 363 if ( ioctl( d->handle, SNDCTL_DSP_GETODELAY, &buffered ) ) {
381 qDebug( "failed to get audio device position" ); 364 qDebug( "failed to get audio device position" );
382 return -1; 365 return -1;
383 } 366 }
384 return buffered; 367 return buffered;
385#endif 368#endif
386} 369}
387 370