Qtopia library API Documentation

sound.cpp

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 #include "config.h"
00037 #include <qmessagebox.h>
00038 #ifndef QT_NO_SOUND
00039 static int WAVsoundDuration(const QString& filename)
00040 {
00041     // bad solution
00042 
00043     // most of this is copied from qsoundqss.cpp
00044 
00045     QFile input(filename);
00046     if ( !input.open(IO_ReadOnly) )
00047     return 0;
00048 
00049     struct QRiffChunk {
00050     char id[4];
00051     Q_UINT32 size;
00052     char data[4/*size*/];
00053     } chunk;
00054 
00055     struct {
00056         Q_INT16 formatTag;
00057         Q_INT16 channels;
00058         Q_INT32 samplesPerSec;
00059         Q_INT32 avgBytesPerSec;
00060         Q_INT16 blockAlign;
00061         Q_INT16 wBitsPerSample;
00062     } chunkdata;
00063 
00064     int total = 0;
00065 
00066     while(1) {
00067     // Keep reading chunks...
00068     const int n = sizeof(chunk)-sizeof(chunk.data);
00069     if ( input.readBlock((char*)&chunk,n) != n )
00070         break;
00071     if ( qstrncmp(chunk.id,"data",4) == 0 ) {
00072         total += chunkdata.avgBytesPerSec ?
00073         chunk.size * 1000 / chunkdata.avgBytesPerSec : 0;
00074 //qDebug("%d bytes of PCM (%dms)", chunk.size,chunkdata.avgBytesPerSec ?  chunk.size * 1000 / chunkdata.avgBytesPerSec : 0);
00075         input.at(input.at()+chunk.size-4);
00076     } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) {
00077         char d[4];
00078         if ( input.readBlock(d,4) != 4 )
00079         return 0;
00080         if ( qstrncmp(d,"WAVE",4) != 0 ) {
00081         // skip
00082 //qDebug("skip %.4s RIFF chunk",d);
00083         if ( chunk.size < 10000000 )
00084             (void)input.at(input.at()+chunk.size-4);
00085         }
00086     } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) {
00087         if ( input.readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) )
00088         return 0;
00089 #define WAVE_FORMAT_PCM 1
00090         if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) {
00091         //qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag);
00092         return 0;
00093         }
00094     } else {
00095 //qDebug("skip %.4s chunk",chunk.id);
00096         // ignored chunk
00097         if ( chunk.size < 10000000 )
00098         (void)input.at(input.at()+chunk.size);
00099     }
00100     }
00101 
00102 //qDebug("%dms",total);
00103     return total;
00104 }
00105 
00106 class SoundData : public QSound {
00107 public:
00108     SoundData ( const QString& name ) :
00109         QSound ( Resource::findSound ( name )),
00110         filename ( Resource::findSound ( name ))
00111     {
00112         loopsleft=0;
00113         ms = WAVsoundDuration(filename);
00114     }
00115 
00116     void playLoop ( int loopcnt = -1 )
00117     {
00118         // needs server support
00119         loopsleft = loopcnt;
00120 
00121         if ( ms )
00122             startTimer ( ms > 50 ? ms-50 : 0 ); // 50 for latency
00123         play ( );
00124     }
00125 
00126     void timerEvent ( QTimerEvent *e )
00127     {
00128         if ( loopsleft >= 0 ) {
00129             if ( --loopsleft <= 0 ) {
00130                 killTimer ( e-> timerId ( ));
00131                 loopsleft = 0;
00132                 return;
00133             }
00134         }
00135         play();
00136     }
00137 
00138     bool isFinished ( ) const
00139     {
00140         return ( loopsleft == 0 );
00141     }
00142 
00143 private:
00144     QString filename;
00145     int loopsleft;
00146     int ms;
00147 };
00148 
00149 #endif
00150 
00154 Sound::Sound(const QString& name)
00155 {
00156 #ifndef QT_NO_SOUND
00157     d = new SoundData(name);
00158 #endif
00159 }
00160 
00162 Sound::~Sound()
00163 {
00164 #ifndef QT_NO_SOUND
00165     delete d;
00166 #endif
00167 }
00168 
00170 void Sound::play()
00171 {
00172 #ifndef QT_NO_SOUND
00173     d->playLoop(1);
00174 #endif
00175 }
00176 
00178 void Sound::playLoop()
00179 {
00180 #ifndef QT_NO_SOUND
00181     d->killTimers();
00182     d->playLoop();
00183 #endif
00184 }
00185 
00187 void Sound::stop()
00188 {
00189 #ifndef QT_NO_SOUND
00190     d->killTimers();
00191 #endif
00192 }
00193 
00194 bool Sound::isFinished() const
00195 {
00196 #ifndef QT_NO_SOUND
00197     return d->isFinished();
00198 #else
00199     return true;
00200 #endif
00201 }
00202 
00206 void Sound::soundAlarm()
00207 {
00208 #ifndef QT_NO_COP
00209     QCopEnvelope( "QPE/TaskBar", "soundAlarm()" );
00210 #endif
00211 }
00212 
00213 
KDE Logo
This file is part of the documentation for OPIE Version 1.5.5.
Documentation copyright © 1997-2003 the KDE developers. 2003 OPIE developers
Generated on Tue Feb 10 20:24:08 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001