Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

sound.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 #include <qpe/resource.h>
00022 #include <qpe/sound.h>
00023 #include <qpe/qcopenvelope_qws.h>
00024 
00025 #include <qsound.h>
00026 #include <qfile.h>
00027 
00028 #include <unistd.h>
00029 #include <fcntl.h>
00030 #include <sys/ioctl.h>
00031 
00032 #ifndef QT_NO_SOUND
00033 #include <sys/soundcard.h>
00034 #endif
00035 
00036 #ifndef QT_NO_SOUND
00037 static int WAVsoundDuration(const QString& filename)
00038 {
00039     // bad solution
00040 
00041     // most of this is copied from qsoundqss.cpp
00042 
00043     QFile input(filename);
00044     if ( !input.open(IO_ReadOnly) )
00045         return 0;
00046 
00047     struct QRiffChunk {
00048         char id[4];
00049         Q_UINT32 size;
00050         char data[4/*size*/];
00051     } chunk;
00052 
00053     struct {
00054         Q_INT16 formatTag;
00055         Q_INT16 channels;
00056         Q_INT32 samplesPerSec;
00057         Q_INT32 avgBytesPerSec;
00058         Q_INT16 blockAlign;
00059         Q_INT16 wBitsPerSample;
00060     } chunkdata;
00061 
00062     int total = 0;
00063 
00064     while(1) {
00065         // Keep reading chunks...
00066         const int n = sizeof(chunk)-sizeof(chunk.data);
00067         if ( input.readBlock((char*)&chunk,n) != n )
00068             break;
00069         if ( qstrncmp(chunk.id,"data",4) == 0 ) {
00070             total += chunkdata.avgBytesPerSec ?
00071                 chunk.size * 1000 / chunkdata.avgBytesPerSec : 0;
00072 //qDebug("%d bytes of PCM (%dms)", chunk.size,chunkdata.avgBytesPerSec ?  chunk.size * 1000 / chunkdata.avgBytesPerSec : 0);
00073             input.at(input.at()+chunk.size-4);
00074         } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) {
00075             char d[4];
00076             if ( input.readBlock(d,4) != 4 )
00077                 return 0;
00078             if ( qstrncmp(d,"WAVE",4) != 0 ) {
00079                 // skip
00080 //qDebug("skip %.4s RIFF chunk",d);
00081                 if ( chunk.size < 10000000 )
00082                     (void)input.at(input.at()+chunk.size-4);
00083             }
00084         } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) {
00085             if ( input.readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) )
00086                 return 0;
00087 #define WAVE_FORMAT_PCM 1
00088             if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) {
00089                 //qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag);
00090                 return 0;
00091             }
00092         } else {
00093 //qDebug("skip %.4s chunk",chunk.id);
00094             // ignored chunk
00095             if ( chunk.size < 10000000 )
00096                 (void)input.at(input.at()+chunk.size);
00097         }
00098     }
00099 
00100 //qDebug("%dms",total);
00101     return total;
00102 }
00103 
00104 class SoundData : public QSound {
00105     Q_OBJECT
00106 signals:
00107     void stopped();
00108 public:
00109         SoundData ( const QString& name ) :
00110                 QSound ( Resource::findSound ( name )),
00111                 filename ( Resource::findSound ( name ))
00112         {
00113                 loopsleft=0;
00114                 ms = WAVsoundDuration(filename);
00115         }
00116 
00117         void playLoop ( int loopcnt = -1 )
00118         {
00119                 // needs server support
00120                 loopsleft = loopcnt;
00121 
00122                 if ( ms )
00123                         startTimer ( ms > 50 ? ms-50 : 0 ); // 50 for latency
00124                 play ( );
00125         }
00126 
00127     void timerEvent ( QTimerEvent *e )
00128     {
00129                 if ( loopsleft >= 0 ) {
00130                         if ( --loopsleft <= 0 ) {
00131                                 killTimer ( e-> timerId ( ));
00132                                 loopsleft = 0;
00133                                 return;
00134                         }
00135                 }
00136                 play();
00137         }
00138 
00139     bool isFinished ( ) const
00140         {
00141             return ( loopsleft == 0 );
00142         }
00143 
00144     /*
00145      * non virtual reimplementation
00146      * @internal
00147      */
00148     void killTimers() {
00149         QObject::killTimers();
00150         emit stopped();
00151     }
00152 
00153 private:
00154         QString filename;
00155         int loopsleft;
00156         int ms;
00157 };
00158 
00159 #endif
00160 
00161 
00162 /*
00163  * @internal
00164  * Using sender() when the slot is called is unsafe!
00165  *
00166  * @param snd  instance
00167  * @param obj  The QObject to be called
00168  * @param slot connect SIGNAL(stopped()) to slot
00169  */
00170 void register_qpe_sound_finished( Sound* snd, QObject* obj, const char* slot ) {
00171 #ifndef QT_NO_SOUND
00172     QObject::connect(snd->d, SIGNAL(stopped()), obj, slot );
00173 #endif
00174 }
00175 
00179 Sound::Sound(const QString& name)
00180 {
00181 #ifndef QT_NO_SOUND
00182     d = new SoundData(name);
00183 #endif
00184 }
00185 
00187 Sound::~Sound()
00188 {
00189 #ifndef QT_NO_SOUND
00190     delete d;
00191 #endif
00192 }
00193 
00195 void Sound::play()
00196 {
00197 #ifndef QT_NO_SOUND
00198     d->killTimers();
00199     d->playLoop(1);
00200 #endif
00201 }
00202 
00204 void Sound::playLoop()
00205 {
00206 #ifndef QT_NO_SOUND
00207     d->killTimers();
00208     d->playLoop();
00209 #endif
00210 }
00211 
00213 void Sound::stop()
00214 {
00215 #ifndef QT_NO_SOUND
00216     d->killTimers();
00217 #endif
00218 }
00219 
00220 bool Sound::isFinished() const
00221 {
00222 #ifndef QT_NO_SOUND
00223     return d->isFinished();
00224 #else
00225         return true;
00226 #endif
00227 }
00228 
00232 void Sound::soundAlarm()
00233 {
00234 #ifndef QT_NO_COP
00235     QCopEnvelope( "QPE/TaskBar", "soundAlarm()" );
00236 #endif
00237 }
00238 
00239 
00252 #ifndef QT_NO_SOUND
00253 #include "sound.moc"
00254 #endif

Generated on Sat Nov 5 16:16:41 2005 for OPIE by  doxygen 1.4.2