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.cpp156
1 files changed, 86 insertions, 70 deletions
diff --git a/core/multimedia/opieplayer/audiodevice.cpp b/core/multimedia/opieplayer/audiodevice.cpp
index 11fd9e8..7b3700a 100644
--- a/core/multimedia/opieplayer/audiodevice.cpp
+++ b/core/multimedia/opieplayer/audiodevice.cpp
@@ -1,7 +1,7 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of the 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
@@ -17,11 +17,8 @@
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
21
22 20
23#include <stdlib.h> 21#include <stdlib.h>
24#include <stdio.h>
25#include <qpe/qpeapplication.h> 22#include <qpe/qpeapplication.h>
26#include <qpe/config.h> 23#include <qpe/config.h>
27#include "audiodevice.h" 24#include "audiodevice.h"
@@ -109,18 +106,17 @@ void AudioDevice::getVolume( unsigned int& leftVolume, unsigned int& rightVolume
109 formatData.wBitsPerSample = 16; 106 formatData.wBitsPerSample = 16;
110 waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL); 107 waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL);
111 if ( waveOutGetVolume( handle, (LPDWORD)&volume ) ) 108 if ( waveOutGetVolume( handle, (LPDWORD)&volume ) )
112// qDebug( "get volume of audio device failed" ); 109 qDebug( "get volume of audio device failed" );
113 waveOutClose( handle ); 110 waveOutClose( handle );
114 leftVolume = volume & 0xFFFF; 111 leftVolume = volume & 0xFFFF;
115 rightVolume = volume >> 16; 112 rightVolume = volume >> 16;
116#else 113#else
117 int mixerHandle = open( "/dev/mixer", O_RDWR ); 114 int mixerHandle = open( "/dev/mixer", O_RDWR );
118 if ( mixerHandle >= 0 ) { 115 if ( mixerHandle >= 0 ) {
119 if(ioctl( mixerHandle, MIXER_READ(0), &volume )==-1) 116 ioctl( mixerHandle, MIXER_READ(0), &volume );
120 perror("ioctl(\"MIXER_READ\")");
121 close( mixerHandle ); 117 close( mixerHandle );
122 } else 118 } else
123 perror("open(\"/dev/mixer\")"); 119 qDebug( "get volume of audio device failed" );
124 leftVolume = ((volume & 0x00FF) << 16) / 101; 120 leftVolume = ((volume & 0x00FF) << 16) / 101;
125 rightVolume = ((volume & 0xFF00) << 8) / 101; 121 rightVolume = ((volume & 0xFF00) << 8) / 101;
126#endif 122#endif
@@ -130,13 +126,13 @@ void AudioDevice::getVolume( unsigned int& leftVolume, unsigned int& rightVolume
130void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume, bool muted ) { 126void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume, bool muted ) {
131 AudioDevicePrivate::muted = muted; 127 AudioDevicePrivate::muted = muted;
132 if ( muted ) { 128 if ( muted ) {
133 AudioDevicePrivate::leftVolume = leftVolume; 129 AudioDevicePrivate::leftVolume = leftVolume;
134 AudioDevicePrivate::rightVolume = rightVolume; 130 AudioDevicePrivate::rightVolume = rightVolume;
135 leftVolume = 0; 131 leftVolume = 0;
136 rightVolume = 0; 132 rightVolume = 0;
137 } else { 133 } else {
138 leftVolume = ( (int) leftVolume < 0 ) ? 0 : (( leftVolume > 0xFFFF ) ? 0xFFFF : leftVolume ); 134 leftVolume = ( (int) leftVolume < 0 ) ? 0 : (( leftVolume > 0xFFFF ) ? 0xFFFF : leftVolume );
139 rightVolume = ( (int)rightVolume < 0 ) ? 0 : (( rightVolume > 0xFFFF ) ? 0xFFFF : rightVolume ); 135 rightVolume = ( (int)rightVolume < 0 ) ? 0 : (( rightVolume > 0xFFFF ) ? 0xFFFF : rightVolume );
140 } 136 }
141#ifdef Q_OS_WIN32 137#ifdef Q_OS_WIN32
142 HWAVEOUT handle; 138 HWAVEOUT handle;
@@ -151,7 +147,7 @@ void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume,
151 waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL); 147 waveOutOpen(&handle, WAVE_MAPPER, &formatData, 0L, 0L, CALLBACK_NULL);
152 unsigned int volume = (rightVolume << 16) | leftVolume; 148 unsigned int volume = (rightVolume << 16) | leftVolume;
153 if ( waveOutSetVolume( handle, volume ) ) 149 if ( waveOutSetVolume( handle, volume ) )
154// qDebug( "set volume of audio device failed" ); 150 qDebug( "set volume of audio device failed" );
155 waveOutClose( handle ); 151 waveOutClose( handle );
156#else 152#else
157 // Volume can be from 0 to 100 which is 101 distinct values 153 // Volume can be from 0 to 100 which is 101 distinct values
@@ -162,12 +158,10 @@ void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume,
162 unsigned int volume = ((rV << 8) & 0xFF00) | (lV & 0x00FF); 158 unsigned int volume = ((rV << 8) & 0xFF00) | (lV & 0x00FF);
163 int mixerHandle = 0; 159 int mixerHandle = 0;
164 if ( ( mixerHandle = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { 160 if ( ( mixerHandle = open( "/dev/mixer", O_RDWR ) ) >= 0 ) {
165 if(ioctl( mixerHandle, MIXER_WRITE(0), &volume ) ==-1) 161 ioctl( mixerHandle, MIXER_WRITE(0), &volume );
166 perror("ioctl(\"MIXER_WRITE\")");
167 close( mixerHandle ); 162 close( mixerHandle );
168 } else 163 } else
169 perror("open(\"/dev/mixer\")"); 164 qDebug( "set volume of audio device failed" );
170
171# else 165# else
172 // This is the way this has to be done now I guess, doesn't allow for 166 // This is the way this has to be done now I guess, doesn't allow for
173 // independant right and left channel setting, or setting for different outputs 167 // independant right and left channel setting, or setting for different outputs
@@ -192,47 +186,68 @@ AudioDevice::AudioDevice( unsigned int f, unsigned int chs, unsigned int bps ) {
192 d->frequency = f; 186 d->frequency = f;
193 d->channels = chs; 187 d->channels = chs;
194 d->bytesPerSample = bps; 188 d->bytesPerSample = bps;
195// qDebug("%d",bps);
196 int format=0;
197 if( bps == 8) format = AFMT_U8;
198 else if( bps <= 0) format = AFMT_S16_LE;
199 else format = AFMT_S16_LE;
200 189
201// qDebug("AD- freq %d, channels %d, b/sample %d, bitrate %d",f,chs,bps,format);
202 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) ); 190 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) );
203 191
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
204 225
205 int fragments = 0x10000 * 8 + sound_fragment_shift; 226 int fragments = 0x10000 * 8 + sound_fragment_shift;
227 int format = AFMT_S16_LE;
206 int capabilities = 0; 228 int capabilities = 0;
207 229
208#ifdef KEEP_DEVICE_OPEN 230#ifdef KEEP_DEVICE_OPEN
209 if ( AudioDevicePrivate::dspFd == 0 ) { 231 if ( AudioDevicePrivate::dspFd == 0 ) {
210#endif 232#endif
211 if ( ( d->handle = ::open( "/dev/dsp", O_WRONLY ) ) < 0 ) { 233 if ( ( d->handle = ::open( "/dev/dsp", O_WRONLY ) ) < 0 ) {
212 perror("open(\"/dev/dsp\") sending to /dev/null instead"); 234 qDebug( "error opening audio device /dev/dsp, sending data to /dev/null instead" );
213 d->handle = ::open( "/dev/null", O_WRONLY ); 235 d->handle = ::open( "/dev/null", O_WRONLY );
214 } 236 }
215#ifdef KEEP_DEVICE_OPEN 237#ifdef KEEP_DEVICE_OPEN
216 AudioDevicePrivate::dspFd = d->handle; 238 AudioDevicePrivate::dspFd = d->handle;
217 } else { 239 } else {
218 d->handle = AudioDevicePrivate::dspFd; 240 d->handle = AudioDevicePrivate::dspFd;
219 } 241 }
220#endif 242#endif
221 243
222 if(ioctl( d->handle, SNDCTL_DSP_GETCAPS, &capabilities )==-1) 244 ioctl( d->handle, SNDCTL_DSP_GETCAPS, &capabilities );
223 perror("ioctl(\"SNDCTL_DSP_GETCAPS\")"); 245 ioctl( d->handle, SNDCTL_DSP_SETFRAGMENT, &fragments );
224 if(ioctl( d->handle, SNDCTL_DSP_SETFRAGMENT, &fragments )==-1) 246 ioctl( d->handle, SNDCTL_DSP_SETFMT, &format );
225 perror("ioctl(\"SNDCTL_DSP_SETFRAGMENT\")"); 247 ioctl( d->handle, SNDCTL_DSP_SPEED, &d->frequency );
226 if(ioctl( d->handle, SNDCTL_DSP_SETFMT, & format )==-1)
227 perror("ioctl(\"SNDCTL_DSP_SETFMT\")");
228 qDebug("freq %d", d->frequency);
229 if(ioctl( d->handle, SNDCTL_DSP_SPEED, &d->frequency )==-1)
230 perror("ioctl(\"SNDCTL_DSP_SPEED\")");
231 qDebug("channels %d",d->channels);
232 if ( ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ) == -1 ) { 248 if ( ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ) == -1 ) {
233 d->channels = ( d->channels == 1 ) ? 2 : d->channels; 249 d->channels = ( d->channels == 1 ) ? 2 : d->channels;
234 if(ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels )==-1) 250 ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels );
235 perror("ioctl(\"SNDCTL_DSP_CHANNELS\")");
236 } 251 }
237 252
238 d->bufferSize = sound_fragment_bytes; 253 d->bufferSize = sound_fragment_bytes;
@@ -240,12 +255,13 @@ AudioDevice::AudioDevice( unsigned int f, unsigned int chs, unsigned int bps ) {
240 d->unwritten = 0; 255 d->unwritten = 0;
241 d->can_GETOSPACE = TRUE; // until we find otherwise 256 d->can_GETOSPACE = TRUE; // until we find otherwise
242 257
243 //if ( chs != d->channels ) qDebug( "Wanted %d, got %d channels", chs, d->channels ); 258 //if ( chs != d->channels ) qDebug( "Wanted %d, got %d channels", chs, d->channels );
244 //if ( f != d->frequency ) qDebug( "wanted %dHz, got %dHz", f, d->frequency ); 259 //if ( f != d->frequency ) qDebug( "wanted %dHz, got %dHz", f, d->frequency );
245 //if ( capabilities & DSP_CAP_BATCH ) qDebug( "Sound card has local buffer" ); 260 //if ( capabilities & DSP_CAP_BATCH ) qDebug( "Sound card has local buffer" );
246 //if ( capabilities & DSP_CAP_REALTIME )qDebug( "Sound card has realtime sync" ); 261 //if ( capabilities & DSP_CAP_REALTIME )qDebug( "Sound card has realtime sync" );
247 //if ( capabilities & DSP_CAP_TRIGGER ) qDebug( "Sound card has precise trigger" ); 262 //if ( capabilities & DSP_CAP_TRIGGER ) qDebug( "Sound card has precise trigger" );
248 //if ( capabilities & DSP_CAP_MMAP ) qDebug( "Sound card can mmap" ); 263 //if ( capabilities & DSP_CAP_MMAP ) qDebug( "Sound card can mmap" );
264#endif
249} 265}
250 266
251 267
@@ -254,7 +270,7 @@ AudioDevice::~AudioDevice() {
254 waveOutClose( (HWAVEOUT)d->handle ); 270 waveOutClose( (HWAVEOUT)d->handle );
255#else 271#else
256# ifndef KEEP_DEVICE_OPEN 272# ifndef KEEP_DEVICE_OPEN
257 close( d->handle ); // Now it should be safe to shut the handle 273 close( d->handle ); // Now it should be safe to shut the handle
258# endif 274# endif
259 delete d->unwrittenBuffer; 275 delete d->unwrittenBuffer;
260 delete d; 276 delete d;
@@ -281,15 +297,15 @@ void AudioDevice::write( char *buffer, unsigned int length )
281 waveOutPrepareHeader( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) ); 297 waveOutPrepareHeader( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) );
282 // waveOutWrite returns immediately. the data is sent in the background. 298 // waveOutWrite returns immediately. the data is sent in the background.
283 if ( waveOutWrite( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) ) ) 299 if ( waveOutWrite( (HWAVEOUT)d->handle, lpWaveHdr, sizeof(WAVEHDR) ) )
284 qDebug( "failed to write block to audio device" ); 300 qDebug( "failed to write block to audio device" );
285 // emit completedIO(); 301 // emit completedIO();
286#else 302#else
287 int t = ::write( d->handle, buffer, length ); 303 int t = ::write( d->handle, buffer, length );
288 if ( t<0 ) t = 0; 304 if ( t<0 ) t = 0;
289 if ( t != (int)length) { 305 if ( t != (int)length) {
290 qDebug("Ahhh!! memcpys 1"); 306 qDebug("Ahhh!! memcpys 1");
291 memcpy(d->unwrittenBuffer,buffer+t,length-t); 307 memcpy(d->unwrittenBuffer,buffer+t,length-t);
292 d->unwritten = length-t; 308 d->unwritten = length-t;
293 } 309 }
294#endif 310#endif
295} 311}
@@ -325,27 +341,27 @@ unsigned int AudioDevice::canWrite() const
325#else 341#else
326 audio_buf_info info; 342 audio_buf_info info;
327 if ( d->can_GETOSPACE && ioctl(d->handle,SNDCTL_DSP_GETOSPACE,&info) ) { 343 if ( d->can_GETOSPACE && ioctl(d->handle,SNDCTL_DSP_GETOSPACE,&info) ) {
328 d->can_GETOSPACE = FALSE; 344 d->can_GETOSPACE = FALSE;
329 fcntl( d->handle, F_SETFL, O_NONBLOCK ); 345 fcntl( d->handle, F_SETFL, O_NONBLOCK );
330 } 346 }
331 if ( d->can_GETOSPACE ) { 347 if ( d->can_GETOSPACE ) {
332 int t = info.fragments * sound_fragment_bytes; 348 int t = info.fragments * sound_fragment_bytes;
333 return QMIN(t,(int)bufferSize()); 349 return QMIN(t,(int)bufferSize());
334 } else { 350 } else {
335 if ( d->unwritten ) { 351 if ( d->unwritten ) {
336 int t = ::write( d->handle, d->unwrittenBuffer, d->unwritten ); 352 int t = ::write( d->handle, d->unwrittenBuffer, d->unwritten );
337 if ( t<0 ) t = 0; 353 if ( t<0 ) t = 0;
338 if ( (unsigned)t!=d->unwritten ) { 354 if ( (unsigned)t!=d->unwritten ) {
339 memcpy(d->unwrittenBuffer,d->unwrittenBuffer+t,d->unwritten-t); 355 memcpy(d->unwrittenBuffer,d->unwrittenBuffer+t,d->unwritten-t);
340 d->unwritten -= t; 356 d->unwritten -= t;
341 } else { 357 } else {
342 d->unwritten = 0; 358 d->unwritten = 0;
343 } 359 }
344 } 360 }
345 if ( d->unwritten ) 361 if ( d->unwritten )
346 return 0; 362 return 0;
347 else 363 else
348 return d->bufferSize; 364 return d->bufferSize;
349 } 365 }
350#endif 366#endif
351} 367}
@@ -355,15 +371,15 @@ int AudioDevice::bytesWritten() {
355#ifdef Q_OS_WIN32 371#ifdef Q_OS_WIN32
356 MMTIME pmmt = { TIME_BYTES, 0 }; 372 MMTIME pmmt = { TIME_BYTES, 0 };
357 if ( ( waveOutGetPosition( (HWAVEOUT)d->handle, &pmmt, sizeof(MMTIME) ) != MMSYSERR_NOERROR ) || ( pmmt.wType != TIME_BYTES ) ) { 373 if ( ( waveOutGetPosition( (HWAVEOUT)d->handle, &pmmt, sizeof(MMTIME) ) != MMSYSERR_NOERROR ) || ( pmmt.wType != TIME_BYTES ) ) {
358 qDebug( "failed to get audio device position" ); 374 qDebug( "failed to get audio device position" );
359 return -1; 375 return -1;
360 } 376 }
361 return pmmt.u.cb; 377 return pmmt.u.cb;
362#else 378#else
363 int buffered = 0; 379 int buffered = 0;
364 if ( ioctl( d->handle, SNDCTL_DSP_GETODELAY, &buffered ) ) { 380 if ( ioctl( d->handle, SNDCTL_DSP_GETODELAY, &buffered ) ) {
365 qDebug( "failed to get audio device position" ); 381 qDebug( "failed to get audio device position" );
366 return -1; 382 return -1;
367 } 383 }
368 return buffered; 384 return buffered;
369#endif 385#endif