summaryrefslogtreecommitdiff
path: root/library/sound.cpp
Unidiff
Diffstat (limited to 'library/sound.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/sound.cpp31
1 files changed, 27 insertions, 4 deletions
diff --git a/library/sound.cpp b/library/sound.cpp
index 1ff3b3f..c8704f9 100644
--- a/library/sound.cpp
+++ b/library/sound.cpp
@@ -1,198 +1,221 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of 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**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
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 20
21#include <qpe/resource.h> 21#include <qpe/resource.h>
22#include <qpe/sound.h> 22#include <qpe/sound.h>
23#include <qpe/qcopenvelope_qws.h> 23#include <qpe/qcopenvelope_qws.h>
24 24
25#include <qsound.h> 25#include <qsound.h>
26#include <qfile.h> 26#include <qfile.h>
27 27
28#include <unistd.h> 28#include <unistd.h>
29#include <fcntl.h> 29#include <fcntl.h>
30#include <sys/ioctl.h> 30#include <sys/ioctl.h>
31#include <sys/soundcard.h> 31#include <sys/soundcard.h>
32 32
33#include "config.h" 33#include "config.h"
34#include <qmessagebox.h> 34#include <qmessagebox.h>
35#ifndef QT_NO_SOUND 35#ifndef QT_NO_SOUND
36static int WAVsoundDuration(const QString& filename) 36static int WAVsoundDuration(const QString& filename)
37{ 37{
38 // bad solution 38 // bad solution
39 39
40 // most of this is copied from qsoundqss.cpp 40 // most of this is copied from qsoundqss.cpp
41 41
42 QFile input(filename); 42 QFile input(filename);
43 if ( !input.open(IO_ReadOnly) ) 43 if ( !input.open(IO_ReadOnly) )
44 return 0; 44 return 0;
45 45
46 struct QRiffChunk { 46 struct QRiffChunk {
47 char id[4]; 47 char id[4];
48 Q_UINT32 size; 48 Q_UINT32 size;
49 char data[4/*size*/]; 49 char data[4/*size*/];
50 } chunk; 50 } chunk;
51 51
52 struct { 52 struct {
53 Q_INT16 formatTag; 53 Q_INT16 formatTag;
54 Q_INT16 channels; 54 Q_INT16 channels;
55 Q_INT32 samplesPerSec; 55 Q_INT32 samplesPerSec;
56 Q_INT32 avgBytesPerSec; 56 Q_INT32 avgBytesPerSec;
57 Q_INT16 blockAlign; 57 Q_INT16 blockAlign;
58 Q_INT16 wBitsPerSample; 58 Q_INT16 wBitsPerSample;
59 } chunkdata; 59 } chunkdata;
60 60
61 int total = 0; 61 int total = 0;
62 62
63 while(1) { 63 while(1) {
64 // Keep reading chunks... 64 // Keep reading chunks...
65 const int n = sizeof(chunk)-sizeof(chunk.data); 65 const int n = sizeof(chunk)-sizeof(chunk.data);
66 if ( input.readBlock((char*)&chunk,n) != n ) 66 if ( input.readBlock((char*)&chunk,n) != n )
67 break; 67 break;
68 if ( qstrncmp(chunk.id,"data",4) == 0 ) { 68 if ( qstrncmp(chunk.id,"data",4) == 0 ) {
69 total += chunkdata.avgBytesPerSec ? 69 total += chunkdata.avgBytesPerSec ?
70 chunk.size * 1000 / chunkdata.avgBytesPerSec : 0; 70 chunk.size * 1000 / chunkdata.avgBytesPerSec : 0;
71//qDebug("%d bytes of PCM (%dms)", chunk.size,chunkdata.avgBytesPerSec ? chunk.size * 1000 / chunkdata.avgBytesPerSec : 0); 71//qDebug("%d bytes of PCM (%dms)", chunk.size,chunkdata.avgBytesPerSec ? chunk.size * 1000 / chunkdata.avgBytesPerSec : 0);
72 input.at(input.at()+chunk.size-4); 72 input.at(input.at()+chunk.size-4);
73 } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) { 73 } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) {
74 char d[4]; 74 char d[4];
75 if ( input.readBlock(d,4) != 4 ) 75 if ( input.readBlock(d,4) != 4 )
76 return 0; 76 return 0;
77 if ( qstrncmp(d,"WAVE",4) != 0 ) { 77 if ( qstrncmp(d,"WAVE",4) != 0 ) {
78 // skip 78 // skip
79//qDebug("skip %.4s RIFF chunk",d); 79//qDebug("skip %.4s RIFF chunk",d);
80 if ( chunk.size < 10000000 ) 80 if ( chunk.size < 10000000 )
81 (void)input.at(input.at()+chunk.size-4); 81 (void)input.at(input.at()+chunk.size-4);
82 } 82 }
83 } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) { 83 } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) {
84 if ( input.readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) 84 if ( input.readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) )
85 return 0; 85 return 0;
86#define WAVE_FORMAT_PCM 1 86#define WAVE_FORMAT_PCM 1
87 if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) { 87 if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) {
88 //qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag); 88 //qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag);
89 return 0; 89 return 0;
90 } 90 }
91 } else { 91 } else {
92//qDebug("skip %.4s chunk",chunk.id); 92//qDebug("skip %.4s chunk",chunk.id);
93 // ignored chunk 93 // ignored chunk
94 if ( chunk.size < 10000000 ) 94 if ( chunk.size < 10000000 )
95 (void)input.at(input.at()+chunk.size); 95 (void)input.at(input.at()+chunk.size);
96 } 96 }
97 } 97 }
98 98
99//qDebug("%dms",total); 99//qDebug("%dms",total);
100 return total; 100 return total;
101} 101}
102 102
103class SoundData : public QSound { 103class SoundData : public QSound {
104public: 104public:
105 SoundData ( const QString& name ) : 105 SoundData ( const QString& name ) :
106 QSound ( Resource::findSound ( name )), 106 QSound ( Resource::findSound ( name )),
107 filename ( Resource::findSound ( name )) 107 filename ( Resource::findSound ( name ))
108 { 108 {
109 loopsleft=0; 109 loopsleft=0;
110 ms = WAVsoundDuration(filename); 110 ms = WAVsoundDuration(filename);
111 } 111 }
112 112
113 void playLoop ( int loopcnt = -1 ) 113 void playLoop ( int loopcnt = -1 )
114 { 114 {
115 // needs server support 115 // needs server support
116 loopsleft = loopcnt; 116 loopsleft = loopcnt;
117 117
118 if ( ms ) 118 if ( ms )
119 startTimer ( ms > 50 ? ms-50 : 0 ); // 50 for latency 119 startTimer ( ms > 50 ? ms-50 : 0 ); // 50 for latency
120 play ( ); 120 play ( );
121 } 121 }
122 122
123 void timerEvent ( QTimerEvent *e ) 123 void timerEvent ( QTimerEvent *e )
124 { 124 {
125 if ( loopsleft >= 0 ) { 125 if ( loopsleft >= 0 ) {
126 if ( --loopsleft <= 0 ) { 126 if ( --loopsleft <= 0 ) {
127 killTimer ( e-> timerId ( )); 127 killTimer ( e-> timerId ( ));
128 loopsleft = 0; 128 loopsleft = 0;
129 return; 129 return;
130 } 130 }
131 } 131 }
132 play(); 132 play();
133 } 133 }
134 134
135 bool isFinished ( ) const 135 bool isFinished ( ) const
136 { 136 {
137 return ( loopsleft == 0 ); 137 return ( loopsleft == 0 );
138 } 138 }
139 139
140private: 140private:
141 QString filename; 141 QString filename;
142 int loopsleft; 142 int loopsleft;
143 int ms; 143 int ms;
144}; 144};
145 145
146#endif 146#endif
147 147
148/*! Opens a wave sound file \a name for playing
149 * Resource is used for finding the file
150 **/
148Sound::Sound(const QString& name) 151Sound::Sound(const QString& name)
149{ 152{
150#ifndef QT_NO_SOUND 153#ifndef QT_NO_SOUND
151 d = new SoundData(name); 154 d = new SoundData(name);
152#endif 155#endif
153} 156}
154 157
158/*! Destroys the sound */
155Sound::~Sound() 159Sound::~Sound()
156{ 160{
157#ifndef QT_NO_SOUND 161#ifndef QT_NO_SOUND
158 delete d; 162 delete d;
159#endif 163#endif
160} 164}
161 165
166/*! Play the sound once */
162void Sound::play() 167void Sound::play()
163{ 168{
164#ifndef QT_NO_SOUND 169#ifndef QT_NO_SOUND
165 d->playLoop(1); 170 d->playLoop(1);
166#endif 171#endif
167} 172}
168 173
174/*! Play the sound, repeatedly until stop() is called */
169void Sound::playLoop() 175void Sound::playLoop()
170{ 176{
171#ifndef QT_NO_SOUND 177#ifndef QT_NO_SOUND
172 d->killTimers(); 178 d->killTimers();
173 d->playLoop(); 179 d->playLoop();
174#endif 180#endif
175} 181}
176 182
183/*! Do not repeat the sound after it finishes. This will end a playLoop() */
177void Sound::stop() 184void Sound::stop()
178{ 185{
179#ifndef QT_NO_SOUND 186#ifndef QT_NO_SOUND
180 d->killTimers(); 187 d->killTimers();
181#endif 188#endif
182} 189}
183 190
184bool Sound::isFinished() const 191bool Sound::isFinished() const
185{ 192{
186#ifndef QT_NO_SOUND 193#ifndef QT_NO_SOUND
187 return d->isFinished(); 194 return d->isFinished();
188#else 195#else
189 return true; 196 return true;
190#endif 197#endif
191} 198}
192 199
200/*! Sounds the audible system alarm. This is used for applications such
201 as Calendar when it needs to alarm the user of an event.
202*/
193void Sound::soundAlarm() 203void Sound::soundAlarm()
194{ 204{
195#ifndef QT_NO_COP 205#ifndef QT_NO_COP
196 QCopEnvelope( "QPE/TaskBar", "soundAlarm()" ); 206 QCopEnvelope( "QPE/TaskBar", "soundAlarm()" );
197#endif 207#endif
198} 208}
209
210
211/*! \class Sound
212 \brief The Sound class plays WAVE sound files and can invoke the audible alarm.
213
214 The Sound class is constructed with the .wav music file name. The Sound
215 class retrieves the sound file from the shared Resource class. This class
216 ties together QSound and the available sound resources.
217
218 To sound an audible system alarm, call the static method soundAlarm()
219
220 \ingroup qtopiaemb
221*/