Changeset 769 for trunk/src/multimedia
- Timestamp:
- Aug 2, 2010, 9:27:30 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 21 edited
- 8 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/vendor/nokia/qt/4.6.3 (added) merged: 768 /branches/vendor/nokia/qt/current merged: 767 /branches/vendor/nokia/qt/4.6.2 removed
- Property svn:mergeinfo changed
-
trunk/src/multimedia/audio/audio.pri
r561 r769 42 42 wince*:LIBS += -lcoredll 43 43 44 } else:symbian { 45 INCLUDEPATH += /epoc32/include/mmf/common 46 INCLUDEPATH += /epoc32/include/mmf/server 47 48 HEADERS += $$PWD/qaudio_symbian_p.h \ 49 $$PWD/qaudiodeviceinfo_symbian_p.h \ 50 $$PWD/qaudioinput_symbian_p.h \ 51 $$PWD/qaudiooutput_symbian_p.h 52 53 SOURCES += $$PWD/qaudio_symbian_p.cpp \ 54 $$PWD/qaudiodeviceinfo_symbian_p.cpp \ 55 $$PWD/qaudioinput_symbian_p.cpp \ 56 $$PWD/qaudiooutput_symbian_p.cpp 57 58 LIBS += -lmmfdevsound 44 59 } else:unix { 45 60 unix:contains(QT_CONFIG, alsa) { -
trunk/src/multimedia/audio/qaudiodevicefactory.cpp
r651 r769 59 59 #include "qaudiooutput_alsa_p.h" 60 60 #include "qaudioinput_alsa_p.h" 61 #elif defined(Q_OS_SYMBIAN) 62 #include "qaudiodeviceinfo_symbian_p.h" 63 #include "qaudiooutput_symbian_p.h" 64 #include "qaudioinput_symbian_p.h" 61 65 #endif 62 66 #endif … … 129 133 QList<QAudioDeviceInfo> devices; 130 134 #ifndef QT_NO_AUDIO_BACKEND 131 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) )135 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN)) 132 136 foreach (const QByteArray &handle, QAudioDeviceInfoInternal::availableDevices(mode)) 133 137 devices << QAudioDeviceInfo(QLatin1String("builtin"), handle, mode); … … 159 163 } 160 164 #ifndef QT_NO_AUDIO_BACKEND 161 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) )165 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN)) 162 166 return QAudioDeviceInfo(QLatin1String("builtin"), QAudioDeviceInfoInternal::defaultInputDevice(), QAudio::AudioInput); 163 167 #endif … … 176 180 } 177 181 #ifndef QT_NO_AUDIO_BACKEND 178 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) )182 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN)) 179 183 return QAudioDeviceInfo(QLatin1String("builtin"), QAudioDeviceInfoInternal::defaultOutputDevice(), QAudio::AudioOutput); 180 184 #endif … … 188 192 189 193 #ifndef QT_NO_AUDIO_BACKEND 190 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) )194 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN)) 191 195 if (realm == QLatin1String("builtin")) 192 196 return new QAudioDeviceInfoInternal(handle, mode); … … 217 221 return new QNullInputDevice(); 218 222 #ifndef QT_NO_AUDIO_BACKEND 219 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) )223 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN)) 220 224 if (deviceInfo.realm() == QLatin1String("builtin")) 221 225 return new QAudioInputPrivate(deviceInfo.handle(), format); … … 236 240 return new QNullOutputDevice(); 237 241 #ifndef QT_NO_AUDIO_BACKEND 238 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) )242 #if (defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(HAS_ALSA) || defined(Q_OS_SYMBIAN)) 239 243 if (deviceInfo.realm() == QLatin1String("builtin")) 240 244 return new QAudioOutputPrivate(deviceInfo.handle(), format); -
trunk/src/multimedia/audio/qaudiodeviceinfo.cpp
r651 r769 44 44 #include <QtMultimedia/qaudiodeviceinfo.h> 45 45 46 #include <QtCore/qmap.h> 46 47 47 48 QT_BEGIN_NAMESPACE … … 239 240 QAudioFormat QAudioDeviceInfo::nearestFormat(const QAudioFormat &settings) const 240 241 { 241 return isNull() ? QAudioFormat() : d->info->nearestFormat(settings); 242 if (isFormatSupported(settings)) 243 return settings; 244 245 QAudioFormat nearest = settings; 246 247 nearest.setCodec(QLatin1String("audio/pcm")); 248 249 if (nearest.sampleType() == QAudioFormat::Unknown) { 250 QAudioFormat preferred = preferredFormat(); 251 nearest.setSampleType(preferred.sampleType()); 252 } 253 254 QMap<int,int> testFrequencies; 255 QList<int> frequenciesAvailable = supportedFrequencies(); 256 QMap<int,int> testSampleSizes; 257 QList<int> sampleSizesAvailable = supportedSampleSizes(); 258 259 // Get sorted sampleSizes (equal to and ascending values only) 260 if (sampleSizesAvailable.contains(settings.sampleSize())) 261 testSampleSizes.insert(0,settings.sampleSize()); 262 sampleSizesAvailable.removeAll(settings.sampleSize()); 263 foreach (int size, sampleSizesAvailable) { 264 int larger = (size > settings.sampleSize()) ? size : settings.sampleSize(); 265 int smaller = (size > settings.sampleSize()) ? settings.sampleSize() : size; 266 if (size >= settings.sampleSize()) { 267 int diff = larger - smaller; 268 testSampleSizes.insert(diff, size); 269 } 270 } 271 272 // Get sorted frequencies (equal to and ascending values only) 273 if (frequenciesAvailable.contains(settings.frequency())) 274 testFrequencies.insert(0,settings.frequency()); 275 frequenciesAvailable.removeAll(settings.frequency()); 276 foreach (int frequency, frequenciesAvailable) { 277 int larger = (frequency > settings.frequency()) ? frequency : settings.frequency(); 278 int smaller = (frequency > settings.frequency()) ? settings.frequency() : frequency; 279 if (frequency >= settings.frequency()) { 280 int diff = larger - smaller; 281 testFrequencies.insert(diff, frequency); 282 } 283 } 284 285 // Try to find nearest 286 // Check ascending frequencies, ascending sampleSizes 287 QMapIterator<int, int> sz(testSampleSizes); 288 while (sz.hasNext()) { 289 sz.next(); 290 nearest.setSampleSize(sz.value()); 291 QMapIterator<int, int> i(testFrequencies); 292 while (i.hasNext()) { 293 i.next(); 294 nearest.setFrequency(i.value()); 295 if (isFormatSupported(nearest)) 296 return nearest; 297 } 298 } 299 300 //Fallback 301 return preferredFormat(); 242 302 } 243 303 -
trunk/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp
r651 r769 79 79 device = QLatin1String(dev); 80 80 this->mode = mode; 81 82 updateLists(); 81 83 } 82 84 … … 177 179 178 180 bool failed = false; 179 180 // For now, just accept only audio/pcm codec 181 if(!format.codec().startsWith(QLatin1String("audio/pcm"))) 182 failed = true; 183 184 if(!failed && !(format.channels() == 1 || format.channels() == 2)) 185 failed = true; 186 187 if(!failed) { 188 if(!(format.frequency() == 8000 || format.frequency() == 11025 || format.frequency() == 22050 || 189 format.frequency() == 44100 || format.frequency() == 48000 || format.frequency() == 96000)) 190 failed = true; 191 } 192 193 if(!failed && !(format.sampleSize() == 8 || format.sampleSize() == 16)) 194 failed = true; 181 bool match = false; 182 183 // check codec 184 for( int i = 0; i < codecz.count(); i++) { 185 if (format.codec() == codecz.at(i)) 186 match = true; 187 } 188 if (!match) failed = true; 189 190 // check channel 191 match = false; 192 if (!failed) { 193 for( int i = 0; i < channelz.count(); i++) { 194 if (format.channels() == channelz.at(i)) { 195 match = true; 196 break; 197 } 198 } 199 } 200 if (!match) failed = true; 201 202 // check frequency 203 match = false; 204 if (!failed) { 205 for( int i = 0; i < freqz.count(); i++) { 206 if (format.frequency() == freqz.at(i)) { 207 match = true; 208 break; 209 } 210 } 211 } 212 213 // check sample size 214 match = false; 215 if (!failed) { 216 for( int i = 0; i < sizez.count(); i++) { 217 if (format.sampleSize() == sizez.at(i)) { 218 match = true; 219 break; 220 } 221 } 222 } 223 224 // check byte order 225 match = false; 226 if (!failed) { 227 for( int i = 0; i < byteOrderz.count(); i++) { 228 if (format.byteOrder() == byteOrderz.at(i)) { 229 match = true; 230 break; 231 } 232 } 233 } 234 235 // check sample type 236 match = false; 237 if (!failed) { 238 for( int i = 0; i < typez.count(); i++) { 239 if (format.sampleType() == typez.at(i)) { 240 match = true; 241 break; 242 } 243 } 244 } 195 245 196 246 if(!failed) { … … 333 383 codecz.append(QLatin1String("audio/pcm")); 334 384 } 385 if (freqz.count() > 0) 386 freqz.prepend(8000); 335 387 } 336 388 -
trunk/src/multimedia/audio/qaudioinput.cpp
r651 r769 96 96 format.setSampleType(QAudioFormat::UnSignedInt); 97 97 98 if (QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());98 QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice(); 99 99 if (!info.isFormatSupported(format)) { 100 100 qWarning()<<"default format not supported try to use nearest"; … … 147 147 148 148 \sa QAudioOutput, QAudioDeviceInfo 149 150 \section1 Symbian Platform Security Requirements 151 152 On Symbian, processes which use this class must have the 153 \c UserEnvironment platform security capability. If the client 154 process lacks this capability, calls to either overload of start() 155 will fail. 156 This failure is indicated by the QAudioInput object setting 157 its error() value to \l{QAudio::OpenError} and then emitting a 158 \l{stateChanged()}{stateChanged}(\l{QAudio::StoppedState}) signal. 159 160 Platform security capabilities are added via the 161 \l{qmake-variable-reference.html#target-capability}{TARGET.CAPABILITY} 162 qmake variable. 149 163 */ 150 164 … … 191 205 All that is required is to open the QIODevice. 192 206 207 If able to successfully get audio data from the systems audio device the 208 state() is set to either QAudio::ActiveState or QAudio::IdleState, 209 error() is set to QAudio::NoError and the stateChanged() signal is emitted. 210 211 If a problem occurs during this process the error() is set to QAudio::OpenError, 212 state() is set to QAudio::StoppedState and stateChanged() signal is emitted. 213 214 In either case, the stateChanged() signal may be emitted either synchronously 215 during execution of the start() function or asynchronously after start() has 216 returned to the caller. 217 218 \sa {Symbian Platform Security Requirements} 219 193 220 \sa QIODevice 194 221 */ … … 196 223 void QAudioInput::start(QIODevice* device) 197 224 { 198 /*199 -If currently not StoppedState, stop200 -If previous start was push mode, delete internal QIODevice.201 -open audio input.202 If ok, NoError and ActiveState, else OpenError and StoppedState.203 -emit stateChanged()204 */205 225 d->start(device); 206 226 } … … 211 231 directly. 212 232 233 If able to access the systems audio device the state() is set to 234 QAudio::IdleState, error() is set to QAudio::NoError 235 and the stateChanged() signal is emitted. 236 237 If a problem occurs during this process the error() is set to QAudio::OpenError, 238 state() is set to QAudio::StoppedState and stateChanged() signal is emitted. 239 240 In either case, the stateChanged() signal may be emitted either synchronously 241 during execution of the start() function or asynchronously after start() has 242 returned to the caller. 243 244 \sa {Symbian Platform Security Requirements} 245 213 246 \sa QIODevice 214 247 */ … … 216 249 QIODevice* QAudioInput::start() 217 250 { 218 /*219 -If currently not StoppedState, stop220 -If no internal QIODevice, create one.221 -open audio input.222 -If ok, NoError and IdleState, else OpenError and StoppedState223 -emit stateChanged()224 -return internal QIODevice225 */226 251 return d->start(0); 227 252 } … … 237 262 238 263 /*! 239 Stops the audio input. 264 Stops the audio input, detaching from the system resource. 265 266 Sets error() to QAudio::NoError, state() to QAudio::StoppedState and 267 emit stateChanged() signal. 240 268 */ 241 269 242 270 void QAudioInput::stop() 243 271 { 244 /*245 -If StoppedState, return246 -set to StoppedState247 -detach from audio device248 -emit stateChanged()249 */250 272 d->stop(); 251 273 } … … 257 279 void QAudioInput::reset() 258 280 { 259 /*260 -drop all buffered audio, set buffers to zero.261 -call stop()262 */263 281 d->reset(); 264 282 } … … 266 284 /*! 267 285 Stops processing audio data, preserving buffered audio data. 286 287 Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and 288 emit stateChanged() signal. 289 290 Note: signal will always be emitted during execution of the resume() function. 268 291 */ 269 292 270 293 void QAudioInput::suspend() 271 294 { 272 /*273 -If not ActiveState|IdleState, return274 -stop processing audio, saving all buffered audio data275 -set NoError and SuspendedState276 -emit stateChanged()277 */278 295 d->suspend(); 279 296 } … … 281 298 /*! 282 299 Resumes processing audio data after a suspend(). 300 301 Sets error() to QAudio::NoError. 302 Sets state() to QAudio::ActiveState if you previously called start(QIODevice*). 303 Sets state() to QAudio::IdleState if you previously called start(). 304 emits stateChanged() signal. 283 305 */ 284 306 285 307 void QAudioInput::resume() 286 308 { 287 /*288 -If SuspendedState, return289 -resume audio290 -(PULL MODE): set ActiveState, NoError291 -(PUSH MODE): set IdleState, NoError292 -kick start audio if needed293 -emit stateChanged()294 */295 309 d->resume(); 296 310 } 297 311 298 312 /*! 299 Sets the audio buffer size to \a value milliseconds.313 Sets the audio buffer size to \a value bytes. 300 314 301 315 Note: This function can be called anytime before start(), calls to this … … 312 326 313 327 /*! 314 Returns the audio buffer size in milliseconds.328 Returns the audio buffer size in bytes. 315 329 316 330 If called before start(), returns platform default value. … … 328 342 /*! 329 343 Returns the amount of audio data available to read in bytes. 344 345 NOTE: returned value is only valid while in QAudio::ActiveState or QAudio::IdleState 346 state, otherwise returns zero. 330 347 */ 331 348 … … 353 370 Sets the interval for notify() signal to be emitted. 354 371 This is based on the \a ms of audio data processed 355 not on actual real-time. The resolution of the timer is platform specific. 372 not on actual real-time. 373 The minimum resolution of the timer is platform specific and values 374 should be checked with notifyInterval() to confirm actual value 375 being used. 356 376 */ 357 377 -
trunk/src/multimedia/audio/qaudioinput_alsa_p.cpp
r651 r769 59 59 //#define DEBUG_AUDIO 1 60 60 61 static const int minimumIntervalTime = 50;62 63 61 QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): 64 62 settings(audioFormat) … … 122 120 if(err < 0) 123 121 reset = true; 122 else { 123 bytesAvailable = bytesReady(); 124 if (bytesAvailable <= 0) 125 reset = true; 126 } 124 127 125 128 } else if((err == -ESTRPIPE)||(err == -EIO)) { … … 218 221 pullMode = true; 219 222 audioSource = device; 223 deviceState = QAudio::ActiveState; 220 224 } else { 221 225 //set to push mode 222 226 pullMode = false; 227 deviceState = QAudio::IdleState; 223 228 audioSource = new InputPrivate(this); 224 229 audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered); … … 414 419 415 420 errorState = QAudio::NoError; 416 deviceState = QAudio::ActiveState;417 421 418 422 totalTimeValue = 0; … … 423 427 void QAudioInputPrivate::close() 424 428 { 425 deviceState = QAudio::StoppedState;426 429 timer->stop(); 427 430 … … 440 443 return period_size; 441 444 442 if(deviceState != QAudio::ActiveState )445 if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) 443 446 return 0; 444 447 int frames = snd_pcm_avail_update(handle); 448 if (frames < 0) return frames; 445 449 if((int)frames > (int)buffer_frames) 446 450 frames = buffer_frames; … … 451 455 qint64 QAudioInputPrivate::read(char* data, qint64 len) 452 456 { 453 Q_UNUSED(data)454 457 Q_UNUSED(len) 458 455 459 // Read in some audio data and write it to QIODevice, pull mode 456 460 if ( !handle ) … … 458 462 459 463 bytesAvailable = bytesReady(); 464 465 if (bytesAvailable < 0) { 466 // bytesAvailable as negative is error code, try to recover from it. 467 xrun_recovery(bytesAvailable); 468 bytesAvailable = bytesReady(); 469 if (bytesAvailable < 0) { 470 // recovery failed must stop and set error. 471 close(); 472 errorState = QAudio::IOError; 473 deviceState = QAudio::StoppedState; 474 emit stateChanged(deviceState); 475 return 0; 476 } 477 } 460 478 461 479 int count=0, err = 0; … … 469 487 err = snd_pcm_frames_to_bytes(handle, readFrames); 470 488 #ifdef DEBUG_AUDIO 471 qDebug()<<QString::fromLatin1(" PULL:read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData();489 qDebug()<<QString::fromLatin1("read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); 472 490 #endif 473 491 break; … … 490 508 // got some send it onward 491 509 #ifdef DEBUG_AUDIO 492 qDebug()<<" PULL:frames to write to QIODevice = "<<510 qDebug()<<"frames to write to QIODevice = "<< 493 511 snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes"; 494 512 #endif 495 if(deviceState != QAudio::ActiveState )513 if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) 496 514 return 0; 497 498 qint64 l = audioSource->write(audioBuffer,err); 499 if(l < 0) { 500 close(); 501 errorState = QAudio::IOError; 502 deviceState = QAudio::StoppedState; 503 emit stateChanged(deviceState); 504 } else if(l == 0) { 505 errorState = QAudio::NoError; 506 deviceState = QAudio::IdleState; 515 if (pullMode) { 516 qint64 l = audioSource->write(audioBuffer,err); 517 if(l < 0) { 518 close(); 519 errorState = QAudio::IOError; 520 deviceState = QAudio::StoppedState; 521 emit stateChanged(deviceState); 522 } else if(l == 0) { 523 if (deviceState != QAudio::IdleState) { 524 errorState = QAudio::NoError; 525 deviceState = QAudio::IdleState; 526 emit stateChanged(deviceState); 527 } 528 } else { 529 totalTimeValue += err; 530 resuming = false; 531 if (deviceState != QAudio::ActiveState) { 532 errorState = QAudio::NoError; 533 deviceState = QAudio::ActiveState; 534 emit stateChanged(deviceState); 535 } 536 } 537 return l; 538 507 539 } else { 508 totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.frequency(); 540 memcpy(data,audioBuffer,err); 541 totalTimeValue += err; 509 542 resuming = false; 510 errorState = QAudio::NoError; 511 deviceState = QAudio::ActiveState; 512 } 513 return l; 543 if (deviceState != QAudio::ActiveState) { 544 errorState = QAudio::NoError; 545 deviceState = QAudio::ActiveState; 546 emit stateChanged(deviceState); 547 } 548 return err; 549 } 514 550 } 515 551 return 0; … … 557 593 void QAudioInputPrivate::setNotifyInterval(int ms) 558 594 { 559 if(ms >= minimumIntervalTime) 560 intervalTime = ms; 561 else 562 intervalTime = minimumIntervalTime; 595 intervalTime = qMax(0, ms); 563 596 } 564 597 … … 570 603 qint64 QAudioInputPrivate::processedUSecs() const 571 604 { 572 return totalTimeValue; 605 qint64 result = qint64(1000000) * totalTimeValue / 606 (settings.channels()*(settings.sampleSize()/8)) / 607 settings.frequency(); 608 609 return result; 573 610 } 574 611 … … 608 645 return true; 609 646 610 if( (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {647 if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { 611 648 emit notify(); 612 649 elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; … … 618 655 qint64 QAudioInputPrivate::elapsedUSecs() const 619 656 { 620 if(!handle)621 return 0;622 623 657 if (deviceState == QAudio::StoppedState) 624 658 return 0; 625 659 626 #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)627 snd_pcm_status_t* status;628 snd_pcm_status_alloca(&status);629 630 snd_timestamp_t t1,t2;631 if( snd_pcm_status(handle, status) >= 0) {632 snd_pcm_status_get_tstamp(status,&t1);633 snd_pcm_status_get_trigger_tstamp(status,&t2);634 t1.tv_sec-=t2.tv_sec;635 636 signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec;637 if(l < 0) {638 t1.tv_sec--;639 l = -l;640 l %= 1000000;641 }642 return ((t1.tv_sec * 1000000)+l);643 } else644 return 0;645 #else646 660 return clockStamp.elapsed()*1000; 647 #endif648 661 } 649 662 … … 671 684 qint64 InputPrivate::readData( char* data, qint64 len) 672 685 { 673 // push mode, user read() called 674 if((audioDevice->state() != QAudio::ActiveState) && !audioDevice->resuming) 675 return 0; 676 677 int readFrames; 678 int count=0, err = 0; 679 680 while(count < 5) { 681 int frames = snd_pcm_bytes_to_frames(audioDevice->handle, len); 682 readFrames = snd_pcm_readi(audioDevice->handle, data, frames); 683 if (readFrames >= 0) { 684 err = snd_pcm_frames_to_bytes(audioDevice->handle, readFrames); 685 #ifdef DEBUG_AUDIO 686 qDebug()<<QString::fromLatin1("PUSH: read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData(); 687 #endif 688 break; 689 } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) { 690 audioDevice->errorState = QAudio::IOError; 691 err = 0; 692 break; 693 } else { 694 if(readFrames == -EPIPE) { 695 audioDevice->errorState = QAudio::UnderrunError; 696 err = snd_pcm_prepare(audioDevice->handle); 697 } else if(readFrames == -ESTRPIPE) { 698 err = snd_pcm_prepare(audioDevice->handle); 699 } 700 if(err != 0) break; 701 } 702 count++; 703 } 704 if(err > 0 && readFrames > 0) { 705 audioDevice->totalTimeValue += readFrames*1000/audioDevice->settings.frequency()*1000; 706 audioDevice->deviceState = QAudio::ActiveState; 707 return err; 708 } 709 return 0; 686 return audioDevice->read(data,len); 710 687 } 711 688 -
trunk/src/multimedia/audio/qaudioinput_mac_p.cpp
r651 r769 55 55 #include <QtCore/qdebug.h> 56 56 57 #include <QtMultimedia/qaudiodeviceinfo.h>58 57 #include <QtMultimedia/qaudioinput.h> 59 58 60 59 #include "qaudio_mac_p.h" 61 60 #include "qaudioinput_mac_p.h" 62 61 #include "qaudiodeviceinfo_mac_p.h" 63 62 64 63 QT_BEGIN_NAMESPACE 65 64 66 65 67 namespace 66 namespace QtMultimediaInternal 68 67 { 69 68 … … 170 169 void reset() 171 170 { 172 for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i) 171 for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i) { 173 172 bfs->mBuffers[i].mDataByteSize = dataSize; 173 bfs->mBuffers[i].mData = 0; 174 } 174 175 } 175 176 … … 228 229 QObject(parent), 229 230 m_deviceError(false), 231 m_audioConverter(0), 230 232 m_inputFormat(inputFormat), 231 233 m_outputFormat(outputFormat) … … 239 241 connect(m_flushTimer, SIGNAL(timeout()), SLOT(flushBuffer())); 240 242 241 if ( inputFormat.mSampleRate != outputFormat.mSampleRate) {243 if (toQAudioFormat(inputFormat) != toQAudioFormat(outputFormat)) { 242 244 if (AudioConverterNew(&m_inputFormat, &m_outputFormat, &m_audioConverter) != noErr) { 243 245 qWarning() << "QAudioInput: Unable to create an Audio Converter"; … … 518 520 errorCode = QAudio::OpenError; 519 521 else { 522 audioDeviceInfo = new QAudioDeviceInfoInternal(device, QAudio::AudioInput); 520 523 isOpen = false; 521 524 audioDeviceId = AudioDeviceID(did); … … 524 527 totalFrames = 0; 525 528 audioBuffer = 0; 526 internalBufferSize = default_buffer_size;529 internalBufferSize = QtMultimediaInternal::default_buffer_size; 527 530 clockFrequency = AudioGetHostClockFrequency() / 1000; 528 531 errorCode = QAudio::NoError; … … 538 541 { 539 542 close(); 543 delete audioDeviceInfo; 540 544 } 541 545 … … 575 579 &enable, 576 580 sizeof(enable)) != noErr) { 577 qWarning() << "QAudioInput: Unable dto switch to input mode (Enable Input)";581 qWarning() << "QAudioInput: Unable to switch to input mode (Enable Input)"; 578 582 return false; 579 583 } … … 586 590 &enable, 587 591 sizeof(enable)) != noErr) { 588 qWarning() << "QAudioInput: Unable dto switch to input mode (Disable output)";592 qWarning() << "QAudioInput: Unable to switch to input mode (Disable output)"; 589 593 return false; 590 594 } … … 617 621 618 622 // Set format 623 // Wanted 619 624 streamFormat = toAudioStreamBasicDescription(audioFormat); 620 625 621 size = sizeof(deviceFormat); 622 if (AudioUnitGetProperty(audioUnit, 623 kAudioUnitProperty_StreamFormat, 624 kAudioUnitScope_Input, 625 1, 626 &deviceFormat, 627 &size) != noErr) { 628 qWarning() << "QAudioInput: Unable to retrieve device format"; 629 return false; 630 } 631 632 // If the device frequency is different to the requested use a converter 633 if (deviceFormat.mSampleRate != streamFormat.mSampleRate) { 634 AudioUnitSetProperty(audioUnit, 626 // Required on unit 627 if (audioFormat == audioDeviceInfo->preferredFormat()) { 628 deviceFormat = streamFormat; 629 AudioUnitSetProperty(audioUnit, 635 630 kAudioUnitProperty_StreamFormat, 636 631 kAudioUnitScope_Output, 637 632 1, 638 633 &deviceFormat, 639 sizeof( streamFormat));634 sizeof(deviceFormat)); 640 635 } 641 636 else { 642 AudioUnitSetProperty(audioUnit, 643 kAudioUnitProperty_StreamFormat, 644 kAudioUnitScope_Output, 645 1, 646 &streamFormat, 647 sizeof(streamFormat)); 637 size = sizeof(deviceFormat); 638 if (AudioUnitGetProperty(audioUnit, 639 kAudioUnitProperty_StreamFormat, 640 kAudioUnitScope_Input, 641 1, 642 &deviceFormat, 643 &size) != noErr) { 644 qWarning() << "QAudioInput: Unable to retrieve device format"; 645 return false; 646 } 647 648 if (AudioUnitSetProperty(audioUnit, 649 kAudioUnitProperty_StreamFormat, 650 kAudioUnitScope_Output, 651 1, 652 &deviceFormat, 653 sizeof(deviceFormat)) != noErr) { 654 qWarning() << "QAudioInput: Unable to set device format"; 655 return false; 656 } 648 657 } 649 658 … … 662 671 663 672 // Allocate buffer 664 periodSizeBytes = (numberOfFrames * streamFormat.mSampleRate / deviceFormat.mSampleRate) *665 streamFormat.mBytesPerFrame; 673 periodSizeBytes = numberOfFrames * streamFormat.mBytesPerFrame; 674 666 675 if (internalBufferSize < periodSizeBytes * 2) 667 676 internalBufferSize = periodSizeBytes * 2; … … 669 678 internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame; 670 679 671 audioBuffer = new Q AudioInputBuffer(internalBufferSize,680 audioBuffer = new QtMultimediaInternal::QAudioInputBuffer(internalBufferSize, 672 681 periodSizeBytes, 673 682 deviceFormat, … … 675 684 this); 676 685 677 audioIO = new MacInputDevice(audioBuffer, this);686 audioIO = new QtMultimediaInternal::MacInputDevice(audioBuffer, this); 678 687 679 688 // Init … … 708 717 QIODevice* op = device; 709 718 710 if (! open()) {719 if (!audioFormat.isValid() || !open()) { 711 720 stateCode = QAudio::StoppedState; 712 721 errorCode = QAudio::OpenError; … … 805 814 void QAudioInputPrivate::setNotifyInterval(int milliSeconds) 806 815 { 816 if (intervalTimer->interval() == milliSeconds) 817 return; 818 819 if (milliSeconds <= 0) 820 milliSeconds = 0; 821 807 822 intervalTimer->setInterval(milliSeconds); 808 823 } … … 884 899 { 885 900 audioBuffer->startFlushTimer(); 886 intervalTimer->start(); 901 if (intervalTimer->interval() > 0) 902 intervalTimer->start(); 887 903 } 888 904 -
trunk/src/multimedia/audio/qaudioinput_mac_p.h
r651 r769 75 75 class QTimer; 76 76 class QIODevice; 77 class QAbstractAudioDeviceInfo; 77 78 78 namespace 79 namespace QtMultimediaInternal 79 80 { 80 81 class QAudioInputBuffer; … … 98 99 QAudio::Error errorCode; 99 100 QAudio::State stateCode; 100 Q AudioInputBuffer* audioBuffer;101 QtMultimediaInternal::QAudioInputBuffer* audioBuffer; 101 102 QMutex mutex; 102 103 QWaitCondition threadFinished; … … 105 106 AudioStreamBasicDescription streamFormat; 106 107 AudioStreamBasicDescription deviceFormat; 108 QAbstractAudioDeviceInfo *audioDeviceInfo; 107 109 108 110 QAudioInputPrivate(const QByteArray& device, QAudioFormat const& format); -
trunk/src/multimedia/audio/qaudioinput_win32_p.cpp
r651 r769 57 57 58 58 //#define DEBUG_AUDIO 1 59 60 static CRITICAL_SECTION waveInCriticalSection;61 62 static const int minimumIntervalTime = 50;63 59 64 60 QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): … … 77 73 resuming = false; 78 74 finished = false; 79 80 connect(this,SIGNAL(processMore()),SLOT(deviceReady()));81 82 InitializeCriticalSection(&waveInCriticalSection);83 75 } 84 76 … … 86 78 { 87 79 stop(); 88 DeleteCriticalSection(&waveInCriticalSection);89 80 } 90 81 … … 101 92 return; 102 93 94 QMutexLocker(&qAudio->mutex); 95 103 96 switch(uMsg) { 104 97 case WIM_OPEN: 105 98 break; 106 99 case WIM_DATA: 107 EnterCriticalSection(&waveInCriticalSection);108 100 if(qAudio->waveFreeBlockCount > 0) 109 101 qAudio->waveFreeBlockCount--; 110 102 qAudio->feedback(); 111 LeaveCriticalSection(&waveInCriticalSection);112 103 break; 113 104 case WIM_CLOSE: 114 EnterCriticalSection(&waveInCriticalSection);115 105 qAudio->finished = true; 116 LeaveCriticalSection(&waveInCriticalSection);117 106 break; 118 107 default: … … 159 148 160 149 for(int i = 0; i < count; i++) { 161 waveInUnprepareHeader(hWaveIn, &blocks[i], sizeof(WAVEHDR));150 waveInUnprepareHeader(hWaveIn,blocks, sizeof(WAVEHDR)); 162 151 blocks+=sizeof(WAVEHDR); 163 152 } … … 193 182 pullMode = true; 194 183 audioSource = device; 184 deviceState = QAudio::ActiveState; 195 185 } else { 196 186 //set to push mode 197 187 pullMode = false; 188 deviceState = QAudio::IdleState; 198 189 audioSource = new InputPrivate(this); 199 190 audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered); … … 225 216 header = 0; 226 217 if(buffer_size == 0) { 227 // Default buffer size, 100ms, default period size is 20ms228 buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0. 1;218 // Default buffer size, 200ms, default period size is 40ms 219 buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2; 229 220 period_size = buffer_size/5; 230 221 } else { … … 279 270 } 280 271 281 EnterCriticalSection(&waveInCriticalSection);272 mutex.lock(); 282 273 waveFreeBlockCount = buffer_size/period_size; 283 LeaveCriticalSection(&waveInCriticalSection);274 mutex.unlock(); 284 275 285 276 waveCurrentBlock = 0; … … 307 298 totalTimeValue = 0; 308 299 errorState = QAudio::NoError; 309 deviceState = QAudio::ActiveState;310 300 return true; 311 301 } … … 316 306 return; 317 307 308 deviceState = QAudio::StoppedState; 318 309 waveInReset(hWaveIn); 319 310 waveInClose(hWaveIn); 320 deviceState = QAudio::StoppedState;321 311 322 312 int count = 0; … … 326 316 } 327 317 328 EnterCriticalSection(&waveInCriticalSection); 329 for(int i=0; i<waveFreeBlockCount; i++) { 330 if(waveBlocks[i].dwFlags & WHDR_PREPARED) 331 waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR)); 332 } 333 LeaveCriticalSection(&waveInCriticalSection); 318 mutex.lock(); 319 for(int i=0; i<waveFreeBlockCount; i++) 320 waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR)); 334 321 freeBlocks(waveBlocks); 322 mutex.unlock(); 335 323 } 336 324 … … 353 341 qint64 l = 0; 354 342 qint64 written = 0; 355 356 343 while(!done) { 357 344 // Read in some audio data … … 374 361 375 362 } else { 376 totalTimeValue += waveBlocks[header].dwBytesRecorded 377 /((settings.channels()*settings.sampleSize()/8)) 378 *10000/settings.frequency()*100; 363 totalTimeValue += waveBlocks[header].dwBytesRecorded; 379 364 errorState = QAudio::NoError; 380 deviceState = QAudio::ActiveState; 365 if (deviceState != QAudio::ActiveState) { 366 deviceState = QAudio::ActiveState; 367 emit stateChanged(deviceState); 368 } 381 369 resuming = false; 382 370 } … … 388 376 qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l; 389 377 #endif 390 totalTimeValue += waveBlocks[header].dwBytesRecorded 391 /((settings.channels()*settings.sampleSize()/8)) 392 *10000/settings.frequency()*100; 378 totalTimeValue += waveBlocks[header].dwBytesRecorded; 393 379 errorState = QAudio::NoError; 394 deviceState = QAudio::ActiveState; 380 if (deviceState != QAudio::ActiveState) { 381 deviceState = QAudio::ActiveState; 382 emit stateChanged(deviceState); 383 } 395 384 resuming = false; 396 385 } 397 386 } else { 398 387 //no data, not ready yet, next time 399 return 0;388 break; 400 389 } 401 390 402 391 waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR)); 403 392 404 EnterCriticalSection(&waveInCriticalSection);393 mutex.lock(); 405 394 waveFreeBlockCount++; 406 LeaveCriticalSection(&waveInCriticalSection); 395 mutex.unlock(); 396 407 397 waveBlocks[header].dwBytesRecorded=0; 408 398 waveBlocks[header].dwFlags = 0L; … … 412 402 qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result); 413 403 errorState = QAudio::IOError; 414 EnterCriticalSection(&waveInCriticalSection); 404 405 mutex.lock(); 415 406 waveFreeBlockCount--; 416 LeaveCriticalSection(&waveInCriticalSection); 407 mutex.unlock(); 408 417 409 return 0; 418 410 } … … 421 413 qWarning("QAudioInput: failed to setup block %d,err=%d",header,result); 422 414 errorState = QAudio::IOError; 423 EnterCriticalSection(&waveInCriticalSection); 415 416 mutex.lock(); 424 417 waveFreeBlockCount--; 425 LeaveCriticalSection(&waveInCriticalSection); 418 mutex.unlock(); 419 426 420 return 0; 427 421 } … … 431 425 p+=l; 432 426 433 EnterCriticalSection(&waveInCriticalSection);427 mutex.lock(); 434 428 if(!pullMode) { 435 429 if(l+period_size > len && waveFreeBlockCount == buffer_size/period_size) … … 439 433 done = true; 440 434 } 441 LeaveCriticalSection(&waveInCriticalSection);435 mutex.unlock(); 442 436 443 437 written+=l; … … 463 457 } 464 458 } 465 EnterCriticalSection(&waveInCriticalSection); 459 460 mutex.lock(); 466 461 waveFreeBlockCount = buffer_size/period_size; 467 LeaveCriticalSection(&waveInCriticalSection);462 mutex.unlock(); 468 463 469 464 waveCurrentBlock = 0; … … 493 488 void QAudioInputPrivate::setNotifyInterval(int ms) 494 489 { 495 if(ms >= minimumIntervalTime) 496 intervalTime = ms; 497 else 498 intervalTime = minimumIntervalTime; 490 intervalTime = qMax(0, ms); 499 491 } 500 492 … … 506 498 qint64 QAudioInputPrivate::processedUSecs() const 507 499 { 508 return totalTimeValue; 500 if (deviceState == QAudio::StoppedState) 501 return 0; 502 qint64 result = qint64(1000000) * totalTimeValue / 503 (settings.channels()*(settings.sampleSize()/8)) / 504 settings.frequency(); 505 506 return result; 509 507 } 510 508 … … 524 522 qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT "<<this; 525 523 #endif 524 if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState)) 525 QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection); 526 } 527 528 bool QAudioInputPrivate::deviceReady() 529 { 526 530 bytesAvailable = bytesReady(); 527 528 if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState))529 emit processMore();530 }531 532 bool QAudioInputPrivate::deviceReady()533 {534 531 #ifdef DEBUG_AUDIO 535 532 QTime now(QTime::currentTime()); 536 533 qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT"; 537 534 #endif 535 if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) 536 return true; 537 538 538 if(pullMode) { 539 539 // reads some audio data and writes it to QIODevice … … 544 544 a->trigger(); 545 545 } 546 if(deviceState != QAudio::ActiveState) 547 return true; 548 549 if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { 546 547 if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { 550 548 emit notify(); 551 549 elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; … … 578 576 { 579 577 // push mode, user read() called 580 if(audioDevice->deviceState != QAudio::ActiveState) 578 if(audioDevice->deviceState != QAudio::ActiveState && 579 audioDevice->deviceState != QAudio::IdleState) 581 580 return 0; 582 581 // Read in some audio data -
trunk/src/multimedia/audio/qaudioinput_win32_p.h
r651 r769 63 63 #include <QtCore/qstringlist.h> 64 64 #include <QtCore/qdatetime.h> 65 #include <QtCore/qmutex.h> 65 66 66 67 #include <QtMultimedia/qaudio.h> … … 123 124 int waveCurrentBlock; 124 125 126 QMutex mutex; 127 125 128 static void CALLBACK waveInProc( HWAVEIN hWaveIn, UINT uMsg, 126 129 DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ); -
trunk/src/multimedia/audio/qaudiooutput.cpp
r651 r769 203 203 All that is required is to open the QIODevice. 204 204 205 If able to successfully output audio data to the systems audio device the 206 state() is set to QAudio::ActiveState, error() is set to QAudio::NoError 207 and the stateChanged() signal is emitted. 208 209 If a problem occurs during this process the error() is set to QAudio::OpenError, 210 state() is set to QAudio::StoppedState and stateChanged() signal is emitted. 211 212 In either case, the stateChanged() signal may be emitted either synchronously 213 during execution of the start() function or asynchronously after start() has 214 returned to the caller. 215 205 216 \sa QIODevice 206 217 */ … … 208 219 void QAudioOutput::start(QIODevice* device) 209 220 { 210 /*211 -If currently not StoppedState, stop.212 -If previous start was push mode, delete internal QIODevice.213 -open audio output.214 -If ok, NoError and ActiveState, else OpenError and StoppedState215 -emit stateChanged()216 */217 221 d->start(device); 218 222 } … … 222 226 transfer. This QIODevice can be used to write() audio data directly. 223 227 228 If able to access the systems audio device the state() is set to 229 QAudio::IdleState, error() is set to QAudio::NoError 230 and the stateChanged() signal is emitted. 231 232 If a problem occurs during this process the error() is set to QAudio::OpenError, 233 state() is set to QAudio::StoppedState and stateChanged() signal is emitted. 234 235 In either case, the stateChanged() signal may be emitted either synchronously 236 during execution of the start() function or asynchronously after start() has 237 returned to the caller. 238 224 239 \sa QIODevice 225 240 */ … … 227 242 QIODevice* QAudioOutput::start() 228 243 { 229 /*230 -If currently not StoppedState, stop.231 -If no internal QIODevice, create one.232 -open audio output.233 -If ok, NoError and IdleState, else OpenError and StoppedState234 -emit stateChanged()235 -return internal QIODevice236 */237 244 return d->start(0); 238 245 } 239 246 240 247 /*! 241 Stops the audio output. 248 Stops the audio output, detaching from the system resource. 249 250 Sets error() to QAudio::NoError, state() to QAudio::StoppedState and 251 emit stateChanged() signal. 242 252 */ 243 253 244 254 void QAudioOutput::stop() 245 255 { 246 /*247 -If StoppedState, return248 -set to StoppedState249 -detach from audio device250 -emit stateChanged()251 */252 256 d->stop(); 253 257 } … … 259 263 void QAudioOutput::reset() 260 264 { 261 /*262 -drop all buffered audio, set buffers to zero.263 -call stop()264 */265 265 d->reset(); 266 266 } … … 268 268 /*! 269 269 Stops processing audio data, preserving buffered audio data. 270 271 Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and 272 emit stateChanged() signal. 270 273 */ 271 274 272 275 void QAudioOutput::suspend() 273 276 { 274 /*275 -If not ActiveState|IdleState, return276 -stop processing audio, saving all buffered audio data277 -set NoError and SuspendedState278 -emit stateChanged()279 */280 277 d->suspend(); 281 278 } … … 283 280 /*! 284 281 Resumes processing audio data after a suspend(). 282 283 Sets error() to QAudio::NoError. 284 Sets state() to QAudio::ActiveState if you previously called start(QIODevice*). 285 Sets state() to QAudio::IdleState if you previously called start(). 286 emits stateChanged() signal. 287 288 Note: signal will always be emitted during execution of the resume() function. 285 289 */ 286 290 287 291 void QAudioOutput::resume() 288 292 { 289 /*290 -If SuspendedState, return291 -resume audio292 -(PULL MODE): set ActiveState, NoError293 -(PUSH MODE): set IdleState, NoError294 -kick start audio if needed295 -emit stateChanged()296 */297 293 d->resume(); 298 294 } … … 300 296 /*! 301 297 Returns the free space available in bytes in the audio buffer. 298 299 NOTE: returned value is only valid while in QAudio::ActiveState or QAudio::IdleState 300 state, otherwise returns zero. 302 301 */ 303 302 304 303 int QAudioOutput::bytesFree() const 305 304 { 306 /*307 -If not ActiveState|IdleState, return 0308 -return space available in audio buffer in bytes309 */310 305 return d->bytesFree(); 311 306 } … … 354 349 Sets the interval for notify() signal to be emitted. 355 350 This is based on the \a ms of audio data processed 356 not on actual real-time. The resolution of the timer is platform specific. 351 not on actual real-time. 352 The minimum resolution of the timer is platform specific and values 353 should be checked with notifyInterval() to confirm actual value 354 being used. 357 355 */ 358 356 … … 372 370 373 371 /*! 374 Returns the amount of audio data processed since start()372 Returns the amount of audio data processed by the class since start() 375 373 was called in microseconds. 374 375 Note: The amount of audio data played can be determined by subtracting 376 the microseconds of audio data still in the systems audio buffer. 377 378 \code 379 qint64 bytesInBuffer = bufferSize() - bytesFree(); 380 qint64 usInBuffer = (qint64)(1000000) * bytesInBuffer / ( channels() * sampleSize() / 8 ) / frequency(); 381 qint64 usPlayed = processedUSecs() - usInBuffer; 382 \endcode 376 383 */ 377 384 -
trunk/src/multimedia/audio/qaudiooutput_alsa_p.cpp
r651 r769 59 59 //#define DEBUG_AUDIO 1 60 60 61 static const int minimumIntervalTime = 50;62 63 61 QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): 64 62 settings(audioFormat) … … 85 83 opened = false; 86 84 87 QStringList list1 = QString(QLatin1String(device)).split(QLatin1String(":")); 88 m_device = QByteArray(list1.at(0).toLocal8Bit().constData()); 85 m_device = device; 89 86 90 87 timer = new QTimer(this); … … 260 257 if(deviceState == QAudio::StoppedState) 261 258 return; 259 errorState = QAudio::NoError; 262 260 deviceState = QAudio::StoppedState; 263 261 close(); … … 282 280 unsigned int freakuency=settings.frequency(); 283 281 284 QString dev = Q Latin1String(m_device.constData());282 QString dev = QString(QLatin1String(m_device.constData())); 285 283 QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput); 286 284 if(dev.compare(QLatin1String("default")) == 0) { 287 285 #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) 288 dev = QLatin1String(devices.first() .constData());286 dev = QLatin1String(devices.first()); 289 287 #else 290 288 dev = QLatin1String("hw:0,0"); … … 369 367 } 370 368 if ( !fatal ) { 369 unsigned int maxBufferTime = 0; 370 unsigned int minBufferTime = 0; 371 unsigned int maxPeriodTime = 0; 372 unsigned int minPeriodTime = 0; 373 374 err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &maxBufferTime, &dir); 375 if ( err >= 0) 376 err = snd_pcm_hw_params_get_buffer_time_min(hwparams, &minBufferTime, &dir); 377 if ( err >= 0) 378 err = snd_pcm_hw_params_get_period_time_max(hwparams, &maxPeriodTime, &dir); 379 if ( err >= 0) 380 err = snd_pcm_hw_params_get_period_time_min(hwparams, &minPeriodTime, &dir); 381 382 if ( err < 0 ) { 383 fatal = true; 384 errMessage = QString::fromLatin1("QAudioOutput: buffer/period min and max: err = %1").arg(err); 385 } else { 386 if (maxBufferTime < buffer_time || buffer_time < minBufferTime || maxPeriodTime < period_time || minPeriodTime > period_time) { 387 #ifdef DEBUG_AUDIO 388 qDebug()<<"defaults out of range"; 389 qDebug()<<"pmin="<<minPeriodTime<<", pmax="<<maxPeriodTime<<", bmin="<<minBufferTime<<", bmax="<<maxBufferTime; 390 #endif 391 period_time = minPeriodTime; 392 if (period_time*4 <= maxBufferTime) { 393 // Use 4 periods if possible 394 buffer_time = period_time*4; 395 chunks = 4; 396 } else if (period_time*2 <= maxBufferTime) { 397 // Use 2 periods if possible 398 buffer_time = period_time*2; 399 chunks = 2; 400 } else { 401 qWarning()<<"QAudioOutput: alsa only supports single period!"; 402 fatal = true; 403 } 404 #ifdef DEBUG_AUDIO 405 qDebug()<<"used: buffer_time="<<buffer_time<<", period_time="<<period_time; 406 #endif 407 } 408 } 409 } 410 if ( !fatal ) { 371 411 err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir); 372 412 if ( err < 0 ) { 373 413 fatal = true; 374 414 errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err); 375 415 } 376 416 } … … 443 483 void QAudioOutputPrivate::close() 444 484 { 445 deviceState = QAudio::StoppedState;446 485 timer->stop(); 447 486 … … 495 534 } 496 535 if(err > 0) { 497 totalTimeValue += err *1000000/settings.frequency();536 totalTimeValue += err; 498 537 resuming = false; 499 538 errorState = QAudio::NoError; 500 deviceState = QAudio::ActiveState; 539 if (deviceState != QAudio::ActiveState) { 540 deviceState = QAudio::ActiveState; 541 emit stateChanged(deviceState); 542 } 501 543 return snd_pcm_frames_to_bytes( handle, err ); 502 544 } else … … 530 572 void QAudioOutputPrivate::setNotifyInterval(int ms) 531 573 { 532 if(ms >= minimumIntervalTime) 533 intervalTime = ms; 534 else 535 intervalTime = minimumIntervalTime; 574 intervalTime = qMax(0, ms); 536 575 } 537 576 … … 543 582 qint64 QAudioOutputPrivate::processedUSecs() const 544 583 { 545 return totalTimeValue;584 return qint64(1000000) * totalTimeValue / settings.frequency(); 546 585 } 547 586 … … 563 602 } 564 603 resuming = true; 565 if(pullMode) 566 deviceState = QAudio::ActiveState; 567 else 568 deviceState = QAudio::IdleState; 604 605 deviceState = QAudio::ActiveState; 569 606 570 607 errorState = QAudio::NoError; … … 605 642 void QAudioOutputPrivate::feedback() 606 643 { 607 QMetaObject::invokeMethod(this, SLOT(updateAvailable()), Qt::QueuedConnection); 608 } 644 updateAvailable(); 645 } 646 609 647 610 648 void QAudioOutputPrivate::updateAvailable() … … 638 676 if(deviceState != QAudio::ActiveState) 639 677 return true; 640 write(audioBuffer,l); 678 qint64 bytesWritten = write(audioBuffer,l); 679 if (bytesWritten != l) 680 audioSource->seek(audioSource->pos()-(l-bytesWritten)); 641 681 bytesAvailable = bytesFree(); 642 682 … … 646 686 if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) { 647 687 // Underrun 688 if (deviceState != QAudio::IdleState) { 689 errorState = QAudio::UnderrunError; 690 deviceState = QAudio::IdleState; 691 emit stateChanged(deviceState); 692 } 693 } 694 695 } else if(l < 0) { 696 close(); 697 deviceState = QAudio::StoppedState; 698 errorState = QAudio::IOError; 699 emit stateChanged(deviceState); 700 } 701 } else { 702 bytesAvailable = bytesFree(); 703 if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) { 704 // Underrun 705 if (deviceState != QAudio::IdleState) { 648 706 errorState = QAudio::UnderrunError; 649 707 deviceState = QAudio::IdleState; 650 708 emit stateChanged(deviceState); 651 709 } 652 653 } else if(l < 0) { 654 close(); 655 errorState = QAudio::IOError; 656 emit stateChanged(deviceState); 657 } 658 } else 659 bytesAvailable = bytesFree(); 710 } 711 } 660 712 661 713 if(deviceState != QAudio::ActiveState) 662 714 return true; 663 715 664 if( (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {716 if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { 665 717 emit notify(); 666 718 elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; … … 672 724 qint64 QAudioOutputPrivate::elapsedUSecs() const 673 725 { 674 if(!handle)675 return 0;676 677 726 if (deviceState == QAudio::StoppedState) 678 727 return 0; 679 728 680 #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)681 snd_pcm_status_t* status;682 snd_pcm_status_alloca(&status);683 684 snd_timestamp_t t1,t2;685 if( snd_pcm_status(handle, status) >= 0) {686 snd_pcm_status_get_tstamp(status,&t1);687 snd_pcm_status_get_trigger_tstamp(status,&t2);688 t1.tv_sec-=t2.tv_sec;689 690 signed long l = (signed long)t1.tv_usec - (signed long)t2.tv_usec;691 if(l < 0) {692 t1.tv_sec--;693 l = -l;694 l %= 1000000;695 }696 return ((t1.tv_sec * 1000000)+l);697 } else698 return 0;699 #else700 729 return clockStamp.elapsed()*1000; 701 #endif702 return 0;703 730 } 704 731 -
trunk/src/multimedia/audio/qaudiooutput_mac_p.cpp
r651 r769 71 71 72 72 73 namespace 73 namespace QtMultimediaInternal 74 74 { 75 75 … … 238 238 239 239 public: 240 MacOutputDevice(Q AudioOutputBuffer* audioBuffer, QObject* parent):240 MacOutputDevice(QtMultimediaInternal::QAudioOutputBuffer* audioBuffer, QObject* parent): 241 241 QIODevice(parent), 242 242 m_audioBuffer(audioBuffer) … … 264 264 265 265 private: 266 Q AudioOutputBuffer* m_audioBuffer;266 QtMultimediaInternal::QAudioOutputBuffer* m_audioBuffer; 267 267 }; 268 268 … … 286 286 totalFrames = 0; 287 287 audioBuffer = 0; 288 internalBufferSize = default_buffer_size;288 internalBufferSize = QtMultimediaInternal::default_buffer_size; 289 289 clockFrequency = AudioGetHostClockFrequency() / 1000; 290 290 errorCode = QAudio::NoError; … … 400 400 internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame; 401 401 402 audioBuffer = new Q AudioOutputBuffer(internalBufferSize, periodSizeBytes, audioFormat);402 audioBuffer = new QtMultimediaInternal::QAudioOutputBuffer(internalBufferSize, periodSizeBytes, audioFormat); 403 403 connect(audioBuffer, SIGNAL(readyRead()), SLOT(inputReady())); // Pull 404 404 … … 436 436 QIODevice* op = device; 437 437 438 if (! open()) {438 if (!audioFormat.isValid() || !open()) { 439 439 stateCode = QAudio::StoppedState; 440 440 errorCode = QAudio::OpenError; … … 537 537 void QAudioOutputPrivate::setNotifyInterval(int milliSeconds) 538 538 { 539 if (intervalTimer->interval() == milliSeconds) 540 return; 541 542 if (milliSeconds <= 0) 543 milliSeconds = 0; 544 539 545 intervalTimer->setInterval(milliSeconds); 540 546 } … … 623 629 { 624 630 audioBuffer->startFillTimer(); 625 intervalTimer->start(); 631 if (intervalTimer->interval() > 0) 632 intervalTimer->start(); 626 633 } 627 634 -
trunk/src/multimedia/audio/qaudiooutput_mac_p.h
r651 r769 75 75 class QIODevice; 76 76 77 namespace 77 namespace QtMultimediaInternal 78 78 { 79 79 class QAudioOutputBuffer; … … 97 97 AudioStreamBasicDescription deviceFormat; 98 98 AudioStreamBasicDescription streamFormat; 99 Q AudioOutputBuffer* audioBuffer;99 QtMultimediaInternal::QAudioOutputBuffer* audioBuffer; 100 100 QAtomicInt audioThreadState; 101 101 QWaitCondition threadFinished; -
trunk/src/multimedia/audio/qaudiooutput_win32_p.cpp
r651 r769 56 56 57 57 QT_BEGIN_NAMESPACE 58 59 static CRITICAL_SECTION waveOutCriticalSection;60 61 static const int minimumIntervalTime = 50;62 58 63 59 QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat): … … 76 72 pullMode = true; 77 73 finished = false; 78 InitializeCriticalSection(&waveOutCriticalSection);79 74 } 80 75 81 76 QAudioOutputPrivate::~QAudioOutputPrivate() 82 77 { 83 EnterCriticalSection(&waveOutCriticalSection);78 mutex.lock(); 84 79 finished = true; 85 LeaveCriticalSection(&waveOutCriticalSection);80 mutex.unlock(); 86 81 87 82 close(); 88 DeleteCriticalSection(&waveOutCriticalSection);89 83 } 90 84 … … 100 94 if(!qAudio) 101 95 return; 96 97 QMutexLocker(&qAudio->mutex); 102 98 103 99 switch(uMsg) { … … 108 104 return; 109 105 case WOM_DONE: 110 EnterCriticalSection(&waveOutCriticalSection);111 106 if(qAudio->finished || qAudio->buffer_size == 0 || qAudio->period_size == 0) { 112 LeaveCriticalSection(&waveOutCriticalSection);113 107 return; 114 108 } … … 117 111 qAudio->waveFreeBlockCount = qAudio->buffer_size/qAudio->period_size; 118 112 qAudio->feedback(); 119 LeaveCriticalSection(&waveOutCriticalSection);120 113 break; 121 114 default: … … 153 146 154 147 for(int i = 0; i < count; i++) { 155 waveOutUnprepareHeader(hWaveOut, &blocks[i], sizeof(WAVEHDR));148 waveOutUnprepareHeader(hWaveOut,blocks, sizeof(WAVEHDR)); 156 149 blocks+=sizeof(WAVEHDR); 157 150 } … … 212 205 qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()"; 213 206 #endif 207 if (!(settings.frequency() >= 8000 && settings.frequency() <= 48000)) { 208 errorState = QAudio::OpenError; 209 deviceState = QAudio::StoppedState; 210 emit stateChanged(deviceState); 211 qWarning("QAudioOutput: open error, frequency out of range."); 212 return false; 213 } 214 214 if(buffer_size == 0) { 215 215 // Default buffer size, 200ms, default period size is 40ms … … 221 221 waveBlocks = allocateBlocks(period_size, buffer_size/period_size); 222 222 223 EnterCriticalSection(&waveOutCriticalSection);223 mutex.lock(); 224 224 waveFreeBlockCount = buffer_size/period_size; 225 LeaveCriticalSection(&waveOutCriticalSection);225 mutex.unlock(); 226 226 227 227 waveCurrentBlock = 0; … … 290 290 291 291 deviceState = QAudio::StoppedState; 292 errorState = QAudio::NoError; 292 293 int delay = (buffer_size-bytesFree())*1000/(settings.frequency() 293 294 *settings.channels()*(settings.sampleSize()/8)); … … 328 329 void QAudioOutputPrivate::setNotifyInterval(int ms) 329 330 { 330 if(ms >= minimumIntervalTime) 331 intervalTime = ms; 332 else 333 intervalTime = minimumIntervalTime; 331 intervalTime = qMax(0, ms); 334 332 } 335 333 … … 341 339 qint64 QAudioOutputPrivate::processedUSecs() const 342 340 { 343 return totalTimeValue; 341 if (deviceState == QAudio::StoppedState) 342 return 0; 343 qint64 result = qint64(1000000) * totalTimeValue / 344 (settings.channels()*(settings.sampleSize()/8)) / 345 settings.frequency(); 346 347 return result; 344 348 } 345 349 … … 347 351 { 348 352 // Write out some audio data 353 if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) 354 return 0; 349 355 350 356 char* p = (char*)data; … … 355 361 current = &waveBlocks[waveCurrentBlock]; 356 362 while(l > 0) { 357 EnterCriticalSection(&waveOutCriticalSection);363 mutex.lock(); 358 364 if(waveFreeBlockCount==0) { 359 LeaveCriticalSection(&waveOutCriticalSection);365 mutex.unlock(); 360 366 break; 361 367 } 362 LeaveCriticalSection(&waveOutCriticalSection);368 mutex.unlock(); 363 369 364 370 if(current->dwFlags & WHDR_PREPARED) … … 377 383 waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); 378 384 379 EnterCriticalSection(&waveOutCriticalSection);385 mutex.lock(); 380 386 waveFreeBlockCount--; 381 LeaveCriticalSection(&waveOutCriticalSection);382 387 #ifdef DEBUG_AUDIO 383 EnterCriticalSection(&waveOutCriticalSection);384 388 qDebug("write out l=%d, waveFreeBlockCount=%d", 385 389 current->dwBufferLength,waveFreeBlockCount); 386 LeaveCriticalSection(&waveOutCriticalSection);387 390 #endif 388 totalTimeValue += current->dwBufferLength 389 /(settings.channels()*(settings.sampleSize()/8)) 390 *1000000/settings.frequency();; 391 mutex.unlock(); 392 totalTimeValue += current->dwBufferLength; 391 393 waveCurrentBlock++; 392 394 waveCurrentBlock %= buffer_size/period_size; 393 395 current = &waveBlocks[waveCurrentBlock]; 394 396 current->dwUser = 0; 397 errorState = QAudio::NoError; 398 if (deviceState != QAudio::ActiveState) { 399 deviceState = QAudio::ActiveState; 400 emit stateChanged(deviceState); 401 } 395 402 } 396 403 return (len-l); … … 410 417 void QAudioOutputPrivate::suspend() 411 418 { 412 if(deviceState == QAudio::ActiveState) { 419 if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState) { 420 int delay = (buffer_size-bytesFree())*1000/(settings.frequency() 421 *settings.channels()*(settings.sampleSize()/8)); 413 422 waveOutPause(hWaveOut); 423 Sleep(delay+10); 414 424 deviceState = QAudio::SuspendedState; 415 425 errorState = QAudio::NoError; … … 434 444 bool QAudioOutputPrivate::deviceReady() 435 445 { 446 if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState) 447 return false; 448 436 449 if(pullMode) { 437 450 int chunks = bytesAvailable/period_size; … … 445 458 446 459 bool full=false; 447 EnterCriticalSection(&waveOutCriticalSection); 460 461 mutex.lock(); 448 462 if(waveFreeBlockCount==0) full = true; 449 LeaveCriticalSection(&waveOutCriticalSection); 463 mutex.unlock(); 464 450 465 if (full){ 451 466 #ifdef DEBUG_AUDIO 452 467 qDebug() << "Skipping data as unable to write"; 453 468 #endif 454 if( (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) {469 if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) { 455 470 emit notify(); 456 471 elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; … … 466 481 if(l > 0) { 467 482 int out= write(audioBuffer,l); 468 if(out > 0) 469 deviceState = QAudio::ActiveState; 483 if(out > 0) { 484 if (deviceState != QAudio::ActiveState) { 485 deviceState = QAudio::ActiveState; 486 emit stateChanged(deviceState); 487 } 488 } 489 if ( out < l) { 490 // Didnt write all data 491 audioSource->seek(audioSource->pos()-(l-out)); 492 } 470 493 if(startup) 471 494 waveOutRestart(hWaveOut); … … 474 497 475 498 int check = 0; 476 EnterCriticalSection(&waveOutCriticalSection); 499 500 mutex.lock(); 477 501 check = waveFreeBlockCount; 478 LeaveCriticalSection(&waveOutCriticalSection); 502 mutex.unlock(); 503 479 504 if(check == buffer_size/period_size) { 505 if (deviceState != QAudio::IdleState) { 506 errorState = QAudio::UnderrunError; 507 deviceState = QAudio::IdleState; 508 emit stateChanged(deviceState); 509 } 510 } 511 512 } else if(l < 0) { 513 bytesAvailable = bytesFree(); 514 errorState = QAudio::IOError; 515 } 516 } else { 517 int buffered; 518 519 mutex.lock(); 520 buffered = waveFreeBlockCount; 521 mutex.unlock(); 522 523 if (buffered >= buffer_size/period_size && deviceState == QAudio::ActiveState) { 524 if (deviceState != QAudio::IdleState) { 480 525 errorState = QAudio::UnderrunError; 481 526 deviceState = QAudio::IdleState; 482 527 emit stateChanged(deviceState); 483 528 } 484 485 } else if(l < 0) {486 bytesAvailable = bytesFree();487 errorState = QAudio::IOError;488 529 } 489 530 } 490 if(deviceState != QAudio::ActiveState )531 if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState) 491 532 return true; 492 533 493 if( (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {534 if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { 494 535 emit notify(); 495 536 elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime; -
trunk/src/multimedia/audio/qaudiooutput_win32_p.h
r651 r769 62 62 #include <QtCore/qstringlist.h> 63 63 #include <QtCore/qdatetime.h> 64 #include <QtCore/qmutex.h> 64 65 65 66 #include <QtMultimedia/qaudio.h> … … 120 121 DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 ); 121 122 123 QMutex mutex; 124 122 125 WAVEHDR* allocateBlocks(int size, int count); 123 126 void freeBlocks(WAVEHDR* blockArray); -
trunk/src/multimedia/video/qabstractvideobuffer.cpp
r651 r769 49 49 \class QAbstractVideoBuffer 50 50 \brief The QAbstractVideoBuffer class is an abstraction for video data. 51 \preliminary52 51 \since 4.6 53 52 -
trunk/src/multimedia/video/qabstractvideosurface.cpp
r651 r769 47 47 \class QAbstractVideoSurface 48 48 \brief The QAbstractVideoSurface class is a base class for video presentation surfaces. 49 \preliminary50 49 \since 4.6 51 50 -
trunk/src/multimedia/video/qvideoframe.cpp
r651 r769 103 103 \class QVideoFrame 104 104 \brief The QVideoFrame class provides a representation of a frame of video data. 105 \preliminary106 105 \since 4.6 107 106 -
trunk/src/multimedia/video/qvideosurfaceformat.cpp
r651 r769 137 137 \brief The QVideoSurfaceFormat class specifies the stream format of a video presentation 138 138 surface. 139 \preliminary140 139 \since 4.6 141 140
Note:
See TracChangeset
for help on using the changeset viewer.