src/multimedia/audio/qaudiooutput_alsa_p.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    50 // We mean it.
    50 // We mean it.
    51 //
    51 //
    52 
    52 
    53 #include <QtCore/qcoreapplication.h>
    53 #include <QtCore/qcoreapplication.h>
    54 #include "qaudiooutput_alsa_p.h"
    54 #include "qaudiooutput_alsa_p.h"
       
    55 #include "qaudiodeviceinfo_alsa_p.h"
    55 
    56 
    56 QT_BEGIN_NAMESPACE
    57 QT_BEGIN_NAMESPACE
    57 
    58 
    58 //#define DEBUG_AUDIO 1
    59 //#define DEBUG_AUDIO 1
    59 
    60 
    75     period_time = 20000;
    76     period_time = 20000;
    76     totalTimeValue = 0;
    77     totalTimeValue = 0;
    77     intervalTime = 1000;
    78     intervalTime = 1000;
    78     audioBuffer = 0;
    79     audioBuffer = 0;
    79     errorState = QAudio::NoError;
    80     errorState = QAudio::NoError;
    80     deviceState = QAudio::StopState;
    81     deviceState = QAudio::StoppedState;
    81     audioSource = 0;
    82     audioSource = 0;
    82     pullMode = true;
    83     pullMode = true;
    83     resuming = false;
    84     resuming = false;
    84     opened = false;
    85     opened = false;
    85 
    86 
   213     return snd_pcm_hw_params_set_format( handle, hwparams, pcmformat);
   214     return snd_pcm_hw_params_set_format( handle, hwparams, pcmformat);
   214 }
   215 }
   215 
   216 
   216 QIODevice* QAudioOutputPrivate::start(QIODevice* device)
   217 QIODevice* QAudioOutputPrivate::start(QIODevice* device)
   217 {
   218 {
   218     if(deviceState != QAudio::StopState)
   219     if(deviceState != QAudio::StoppedState)
   219         deviceState = QAudio::StopState;
   220         deviceState = QAudio::StoppedState;
   220 
   221 
   221     errorState = QAudio::NoError;
   222     errorState = QAudio::NoError;
   222 
   223 
   223     // Handle change of mode
   224     // Handle change of mode
   224     if(audioSource && pullMode && !device) {
   225     if(audioSource && pullMode && !device) {
   254     return audioSource;
   255     return audioSource;
   255 }
   256 }
   256 
   257 
   257 void QAudioOutputPrivate::stop()
   258 void QAudioOutputPrivate::stop()
   258 {
   259 {
   259     if(deviceState == QAudio::StopState)
   260     if(deviceState == QAudio::StoppedState)
   260         return;
   261         return;
   261     deviceState = QAudio::StopState;
   262     deviceState = QAudio::StoppedState;
   262     close();
   263     close();
   263     emit stateChanged(deviceState);
   264     emit stateChanged(deviceState);
   264 }
   265 }
   265 
   266 
   266 bool QAudioOutputPrivate::open()
   267 bool QAudioOutputPrivate::open()
   279     int err=-1;
   280     int err=-1;
   280     int count=0;
   281     int count=0;
   281     unsigned int freakuency=settings.frequency();
   282     unsigned int freakuency=settings.frequency();
   282 
   283 
   283     QString dev = QLatin1String(m_device.constData());
   284     QString dev = QLatin1String(m_device.constData());
   284     if(!dev.contains(QLatin1String("default"))) {
   285     QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput);
   285 #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) 
   286     if(dev.compare(QLatin1String("default")) == 0) {
   286         dev = QString(QLatin1String("default:CARD=%1")).arg(QLatin1String(m_device.constData()));
   287 #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
       
   288         dev = QLatin1String(devices.first().constData());
       
   289 #else
       
   290         dev = QLatin1String("hw:0,0");
       
   291 #endif
       
   292     } else {
       
   293 #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
       
   294         dev = QLatin1String(m_device);
   287 #else
   295 #else
   288         int idx = 0;
   296         int idx = 0;
   289         char *name;
   297         char *name;
   290 
   298 
       
   299         QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData());
       
   300 
   291 	while(snd_card_get_name(idx,&name) == 0) {
   301 	while(snd_card_get_name(idx,&name) == 0) {
   292             if(m_device.contains(name))
   302             if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0)
   293                 break;
   303                 break;
   294             idx++;
   304             idx++;
   295 	}
   305 	}
   296         dev = QString(QLatin1String("hw:%1,0")).arg(idx);
   306         dev = QString(QLatin1String("hw:%1,0")).arg(idx);
   297 #endif
   307 #endif
   298     }
   308     }
       
   309 
   299     // Step 1: try and open the device
   310     // Step 1: try and open the device
   300     while((count < 5) && (err < 0)) {
   311     while((count < 5) && (err < 0)) {
   301         err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
   312         err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0);
   302         if(err < 0)
   313         if(err < 0)
   303             count++;
   314             count++;
   304     }
   315     }
   305     if (( err < 0)||(handle == 0)) {
   316     if (( err < 0)||(handle == 0)) {
   306         errorState = QAudio::OpenError;
   317         errorState = QAudio::OpenError;
   307         deviceState = QAudio::StopState;
   318         deviceState = QAudio::StoppedState;
   308         return false;
   319         return false;
   309     }
   320     }
   310     snd_pcm_nonblock( handle, 0 );
   321     snd_pcm_nonblock( handle, 0 );
   311 
   322 
   312     // Step 2: Set the desired HW parameters.
   323     // Step 2: Set the desired HW parameters.
   385         }
   396         }
   386     }
   397     }
   387     if( err < 0) {
   398     if( err < 0) {
   388         qWarning()<<errMessage;
   399         qWarning()<<errMessage;
   389         errorState = QAudio::OpenError;
   400         errorState = QAudio::OpenError;
   390         deviceState = QAudio::StopState;
   401         deviceState = QAudio::StoppedState;
   391         return false;
   402         return false;
   392     }
   403     }
   393     snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
   404     snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
   394     buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames);
   405     buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames);
   395     snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir);
   406     snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir);
   429     return true;
   440     return true;
   430 }
   441 }
   431 
   442 
   432 void QAudioOutputPrivate::close()
   443 void QAudioOutputPrivate::close()
   433 {
   444 {
   434     deviceState = QAudio::StopState;
   445     deviceState = QAudio::StoppedState;
   435     timer->stop();
   446     timer->stop();
   436 
   447 
   437     if ( handle ) {
   448     if ( handle ) {
   438         snd_pcm_drain( handle );
   449         snd_pcm_drain( handle );
   439         snd_pcm_close( handle );
   450         snd_pcm_close( handle );
   492         err = xrun_recovery(err);
   503         err = xrun_recovery(err);
   493 
   504 
   494     if(err < 0) {
   505     if(err < 0) {
   495         close();
   506         close();
   496         errorState = QAudio::FatalError;
   507         errorState = QAudio::FatalError;
   497         deviceState = QAudio::StopState;
   508         deviceState = QAudio::StoppedState;
   498         emit stateChanged(deviceState);
   509         emit stateChanged(deviceState);
   499     }
   510     }
   500     return 0;
   511     return 0;
   501 }
   512 }
   502 
   513 
   505     return period_size;
   516     return period_size;
   506 }
   517 }
   507 
   518 
   508 void QAudioOutputPrivate::setBufferSize(int value)
   519 void QAudioOutputPrivate::setBufferSize(int value)
   509 {
   520 {
   510     if(deviceState == QAudio::StopState)
   521     if(deviceState == QAudio::StoppedState)
   511         buffer_size = value;
   522         buffer_size = value;
   512 }
   523 }
   513 
   524 
   514 int QAudioOutputPrivate::bufferSize() const
   525 int QAudioOutputPrivate::bufferSize() const
   515 {
   526 {
   527 int QAudioOutputPrivate::notifyInterval() const
   538 int QAudioOutputPrivate::notifyInterval() const
   528 {
   539 {
   529     return intervalTime;
   540     return intervalTime;
   530 }
   541 }
   531 
   542 
   532 qint64 QAudioOutputPrivate::totalTime() const
   543 qint64 QAudioOutputPrivate::processedUSecs() const
   533 {
   544 {
   534     return totalTimeValue;
   545     return totalTimeValue;
   535 }
   546 }
   536 
   547 
   537 void QAudioOutputPrivate::resume()
   548 void QAudioOutputPrivate::resume()
   538 {
   549 {
   539     if(deviceState == QAudio::SuspendState) {
   550     if(deviceState == QAudio::SuspendedState) {
   540         int err = 0;
   551         int err = 0;
   541 
   552 
   542         if(handle) {
   553         if(handle) {
   543             err = snd_pcm_prepare( handle );
   554             err = snd_pcm_prepare( handle );
   544             if(err < 0)
   555             if(err < 0)
   569 
   580 
   570 void QAudioOutputPrivate::suspend()
   581 void QAudioOutputPrivate::suspend()
   571 {
   582 {
   572     if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState || resuming) {
   583     if(deviceState == QAudio::ActiveState || deviceState == QAudio::IdleState || resuming) {
   573         timer->stop();
   584         timer->stop();
   574         deviceState = QAudio::SuspendState;
   585         deviceState = QAudio::SuspendedState;
   575         errorState = QAudio::NoError;
   586         errorState = QAudio::NoError;
   576         emit stateChanged(deviceState);
   587         emit stateChanged(deviceState);
   577     }
   588     }
   578 }
   589 }
   579 
   590 
   580 void QAudioOutputPrivate::userFeed()
   591 void QAudioOutputPrivate::userFeed()
   581 {
   592 {
   582     if(deviceState == QAudio::StopState || deviceState == QAudio::SuspendState)
   593     if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState)
   583         return;
   594         return;
   584 #ifdef DEBUG_AUDIO
   595 #ifdef DEBUG_AUDIO
   585     QTime now(QTime::currentTime());
   596     QTime now(QTime::currentTime());
   586     qDebug()<<now.second()<<"s "<<now.msec()<<"ms :userFeed() OUT";
   597     qDebug()<<now.second()<<"s "<<now.msec()<<"ms :userFeed() OUT";
   587 #endif
   598 #endif
   656         timeStamp.restart();
   667         timeStamp.restart();
   657     }
   668     }
   658     return true;
   669     return true;
   659 }
   670 }
   660 
   671 
   661 qint64 QAudioOutputPrivate::clock() const
   672 qint64 QAudioOutputPrivate::elapsedUSecs() const
   662 {
   673 {
   663     if(!handle)
   674     if(!handle)
   664         return 0;
   675         return 0;
   665 
   676 
   666     if (deviceState == QAudio::StopState)
   677     if (deviceState == QAudio::StoppedState)
   667         return 0;
   678         return 0;
   668 
   679 
   669 #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14) 
   680 #if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
   670     snd_pcm_status_t* status;
   681     snd_pcm_status_t* status;
   671     snd_pcm_status_alloca(&status);
   682     snd_pcm_status_alloca(&status);
   672 
   683 
   673     snd_timestamp_t t1,t2;
   684     snd_timestamp_t t1,t2;
   674     if( snd_pcm_status(handle, status) >= 0) {
   685     if( snd_pcm_status(handle, status) >= 0) {