00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "audiodevice.h"
00024
00025
00026 #include <qpe/qpeapplication.h>
00027 #include <qpe/config.h>
00028 #include <opie2/odebug.h>
00029
00030 #if !defined(QT_NO_COP)
00031 #include <qpe/qcopenvelope_qws.h>
00032 #endif
00033
00034
00035 #include <qmessagebox.h>
00036
00037
00038 #include <stdlib.h>
00039 #include <stdio.h>
00040 #include <errno.h>
00041
00042 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
00043 #include <fcntl.h>
00044 #include <sys/ioctl.h>
00045 #include <sys/soundcard.h>
00046 #include <sys/stat.h>
00047 #include <sys/time.h>
00048 #include <sys/types.h>
00049 #include <unistd.h>
00050 #endif
00051
00052 #ifdef OPIE_SOUND_FRAGMENT_SHIFT
00053 static const int sound_fragment_shift = OPIE_SOUND_FRAGMENT_SHIFT;
00054 #else
00055 static const int sound_fragment_shift = 16;
00056 #endif
00057 static const int sound_fragment_bytes = (1<<sound_fragment_shift);
00058
00059
00060
00061 class AudioDevicePrivate {
00062 public:
00063 int handle;
00064 unsigned int frequency;
00065 unsigned int channels;
00066 unsigned int bytesPerSample;
00067 unsigned int bufferSize;
00068
00069 bool can_GETOSPACE;
00070 char* unwrittenBuffer;
00071 unsigned int unwritten;
00072
00073
00074 static int dspFd;
00075 static bool muted;
00076 static unsigned int leftVolume;
00077 static unsigned int rightVolume;
00078 };
00079
00080
00081 #ifdef Q_WS_QWS
00082
00083
00084
00085
00086 #endif
00087
00088
00089 int AudioDevicePrivate::dspFd = 0;
00090 bool AudioDevicePrivate::muted = FALSE;
00091 unsigned int AudioDevicePrivate::leftVolume = 0;
00092 unsigned int AudioDevicePrivate::rightVolume = 0;
00093
00094
00095 void AudioDevice::getVolume( unsigned int& leftVolume, unsigned int& rightVolume, bool &muted ) {
00096 muted = AudioDevicePrivate::muted;
00097 unsigned int volume;
00098 #ifdef QT_QWS_DEVFS
00099 int mixerHandle = open( "/dev/sound/mixer", O_RDWR );
00100 #else
00101 int mixerHandle = open( "/dev/mixer", O_RDWR );
00102 #endif
00103 if ( mixerHandle >= 0 ) {
00104 if(ioctl( mixerHandle, MIXER_READ(0), &volume )==-1)
00105 perror("ioctl(\"MIXER_READ\")");
00106 close( mixerHandle );
00107 } else
00108 perror("open(\"/dev/mixer\")");
00109 leftVolume = ((volume & 0x00FF) << 16) / 101;
00110 rightVolume = ((volume & 0xFF00) << 8) / 101;
00111 }
00112
00113
00114 void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume, bool muted ) {
00115 AudioDevicePrivate::muted = muted;
00116 if ( muted ) {
00117 AudioDevicePrivate::leftVolume = leftVolume;
00118 AudioDevicePrivate::rightVolume = rightVolume;
00119 leftVolume = 0;
00120 rightVolume = 0;
00121 } else {
00122 leftVolume = ( (int) leftVolume < 0 ) ? 0 : (( leftVolume > 0xFFFF ) ? 0xFFFF : leftVolume );
00123 rightVolume = ( (int)rightVolume < 0 ) ? 0 : (( rightVolume > 0xFFFF ) ? 0xFFFF : rightVolume );
00124 }
00125
00126 unsigned int rV = (rightVolume * 101) >> 16;
00127
00128 # if 0
00129 unsigned int lV = (leftVolume * 101) >> 16;
00130 unsigned int volume = ((rV << 8) & 0xFF00) | (lV & 0x00FF);
00131 int mixerHandle = 0;
00132 #ifdef QT_QWS_DEVFS
00133 if ( ( mixerHandle = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) {
00134 #else
00135 if ( ( mixerHandle = open( "/dev/mixer", O_RDWR ) ) >= 0 ) {
00136 #endif
00137 if(ioctl( mixerHandle, MIXER_WRITE(0), &volume ) ==-1)
00138 perror("ioctl(\"MIXER_WRITE\")");
00139 close( mixerHandle );
00140 } else
00141 perror("open(\"/dev/mixer\")");
00142
00143 # else
00144
00145
00146 Config cfg("qpe");
00147 cfg.setGroup("Volume");
00148 cfg.writeEntry("VolumePercent",(int)rV);
00149 # endif
00150
00151
00152
00153 #if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP)
00154
00155 QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << muted;
00156 #endif
00157 }
00158
00159
00160
00161 AudioDevice::AudioDevice( unsigned int f, unsigned int chs, unsigned int bps ) {
00162
00163
00164 d = new AudioDevicePrivate;
00165 d->frequency = f;
00166 d->channels = chs;
00167 d->bytesPerSample = bps;
00168
00169 int format=0;
00170 if( bps == 8) format = AFMT_U8;
00171 else if( bps <= 0) format = AFMT_S16_LE;
00172 else format = AFMT_S16_LE;
00173
00174 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) );
00175
00176 int fragments = 0x10000 * 8 + sound_fragment_shift;
00177 int capabilities = 0;
00178
00179
00180 #ifdef KEEP_DEVICE_OPEN
00181 if ( AudioDevicePrivate::dspFd == 0 ) {
00182 #endif
00183 #ifdef QT_QWS_DEVFS
00184 if ( ( d->handle = ::open( "/dev/sound/dsp", O_WRONLY ) ) < 0 ) {
00185 #else
00186 if ( ( d->handle = ::open( "/dev/dsp", O_WRONLY ) ) < 0 ) {
00187 #endif
00188
00189 perror("open(\"/dev/dsp\")");
00190 QString errorMsg=tr("Somethin's wrong with\nyour sound device.\nopen(\"/dev/dsp\")\n")+(QString)strerror(errno)+tr("\n\nClosing player now.");
00191 QMessageBox::critical(0, "Vmemo", errorMsg, tr("Abort"));
00192 exit(-1);
00193 }
00194 #ifdef KEEP_DEVICE_OPEN
00195 AudioDevicePrivate::dspFd = d->handle;
00196 } else {
00197 d->handle = AudioDevicePrivate::dspFd;
00198 }
00199 #endif
00200
00201 if(ioctl( d->handle, SNDCTL_DSP_GETCAPS, &capabilities )==-1)
00202 perror("ioctl(\"SNDCTL_DSP_GETCAPS\")");
00203 if(ioctl( d->handle, SNDCTL_DSP_SETFRAGMENT, &fragments )==-1)
00204 perror("ioctl(\"SNDCTL_DSP_SETFRAGMENT\")");
00205 if(ioctl( d->handle, SNDCTL_DSP_SETFMT, & format )==-1)
00206 perror("ioctl(\"SNDCTL_DSP_SETFMT\")");
00207
00208 if(ioctl( d->handle, SNDCTL_DSP_SPEED, &d->frequency )==-1)
00209 perror("ioctl(\"SNDCTL_DSP_SPEED\")");
00210
00211 if ( ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ) == -1 ) {
00212 d->channels = ( d->channels == 1 ) ? 2 : d->channels;
00213 if(ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels )==-1)
00214 perror("ioctl(\"SNDCTL_DSP_CHANNELS\")");
00215 }
00216
00217
00218 d->bufferSize = sound_fragment_bytes;
00219 d->unwrittenBuffer = new char[d->bufferSize];
00220 d->unwritten = 0;
00221 d->can_GETOSPACE = TRUE;
00222
00223
00224
00225
00226
00227
00228
00229
00230 }
00231
00232
00233 AudioDevice::~AudioDevice() {
00234
00235
00236
00237 # ifndef KEEP_DEVICE_OPEN
00238 close( d->handle );
00239 # endif
00240 delete d->unwrittenBuffer;
00241 delete d;
00242
00243
00244 }
00245
00246
00247 void AudioDevice::volumeChanged( bool muted )
00248 {
00249 AudioDevicePrivate::muted = muted;
00250 }
00251
00252
00253 void AudioDevice::write( char *buffer, unsigned int length )
00254 {
00255 int t = ::write( d->handle, buffer, length );
00256 if ( t<0 ) t = 0;
00257 if ( t != (int)length) {
00258
00259 memcpy(d->unwrittenBuffer,buffer+t,length-t);
00260 d->unwritten = length-t;
00261 }
00262
00263 }
00264
00265
00266 unsigned int AudioDevice::channels() const
00267 {
00268 return d->channels;
00269 }
00270
00271
00272 unsigned int AudioDevice::frequency() const
00273 {
00274 return d->frequency;
00275 }
00276
00277
00278 unsigned int AudioDevice::bytesPerSample() const
00279 {
00280 return d->bytesPerSample;
00281 }
00282
00283
00284 unsigned int AudioDevice::bufferSize() const
00285 {
00286 return d->bufferSize;
00287 }
00288
00289 unsigned int AudioDevice::canWrite() const
00290 {
00291 audio_buf_info info;
00292 if ( d->can_GETOSPACE && ioctl(d->handle,SNDCTL_DSP_GETOSPACE,&info) ) {
00293 d->can_GETOSPACE = FALSE;
00294 fcntl( d->handle, F_SETFL, O_NONBLOCK );
00295 }
00296 if ( d->can_GETOSPACE ) {
00297 int t = info.fragments * sound_fragment_bytes;
00298 return QMIN(t,(int)bufferSize());
00299 } else {
00300 if ( d->unwritten ) {
00301 int t = ::write( d->handle, d->unwrittenBuffer, d->unwritten );
00302 if ( t<0 ) t = 0;
00303 if ( (unsigned)t!=d->unwritten ) {
00304 memcpy(d->unwrittenBuffer,d->unwrittenBuffer+t,d->unwritten-t);
00305 d->unwritten -= t;
00306 } else {
00307 d->unwritten = 0;
00308 }
00309 }
00310 if ( d->unwritten )
00311 return 0;
00312 else
00313 return d->bufferSize;
00314 }
00315 }
00316
00317
00318 int AudioDevice::bytesWritten() {
00319 int buffered = 0;
00320 if ( ioctl( d->handle, SNDCTL_DSP_GETODELAY, &buffered ) ) {
00321
00322 return -1;
00323 }
00324 return buffered;
00325 }
00326