Changeset 769 for trunk/src/multimedia


Ignore:
Timestamp:
Aug 2, 2010, 9:27:30 PM (15 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
21 edited
8 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/multimedia/audio/audio.pri

    r561 r769  
    4242    wince*:LIBS += -lcoredll
    4343
     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
    4459} else:unix {
    4560    unix:contains(QT_CONFIG, alsa) {
  • trunk/src/multimedia/audio/qaudiodevicefactory.cpp

    r651 r769  
    5959#include "qaudiooutput_alsa_p.h"
    6060#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"
    6165#endif
    6266#endif
     
    129133    QList<QAudioDeviceInfo> devices;
    130134#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))
    132136    foreach (const QByteArray &handle, QAudioDeviceInfoInternal::availableDevices(mode))
    133137        devices << QAudioDeviceInfo(QLatin1String("builtin"), handle, mode);
     
    159163    }
    160164#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))
    162166    return QAudioDeviceInfo(QLatin1String("builtin"), QAudioDeviceInfoInternal::defaultInputDevice(), QAudio::AudioInput);
    163167#endif
     
    176180    }
    177181#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))
    179183    return QAudioDeviceInfo(QLatin1String("builtin"), QAudioDeviceInfoInternal::defaultOutputDevice(), QAudio::AudioOutput);
    180184#endif
     
    188192
    189193#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))
    191195    if (realm == QLatin1String("builtin"))
    192196        return new QAudioDeviceInfoInternal(handle, mode);
     
    217221        return new QNullInputDevice();
    218222#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))
    220224    if (deviceInfo.realm() == QLatin1String("builtin"))
    221225        return new QAudioInputPrivate(deviceInfo.handle(), format);
     
    236240        return new QNullOutputDevice();
    237241#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))
    239243    if (deviceInfo.realm() == QLatin1String("builtin"))
    240244        return new QAudioOutputPrivate(deviceInfo.handle(), format);
  • trunk/src/multimedia/audio/qaudiodeviceinfo.cpp

    r651 r769  
    4444#include <QtMultimedia/qaudiodeviceinfo.h>
    4545
     46#include <QtCore/qmap.h>
    4647
    4748QT_BEGIN_NAMESPACE
     
    239240QAudioFormat QAudioDeviceInfo::nearestFormat(const QAudioFormat &settings) const
    240241{
    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();
    242302}
    243303
  • trunk/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp

    r651 r769  
    7979    device = QLatin1String(dev);
    8080    this->mode = mode;
     81
     82    updateLists();
    8183}
    8284
     
    177179
    178180    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    }
    195245
    196246    if(!failed) {
     
    333383        codecz.append(QLatin1String("audio/pcm"));
    334384    }
     385    if (freqz.count() > 0)
     386        freqz.prepend(8000);
    335387}
    336388
  • trunk/src/multimedia/audio/qaudioinput.cpp

    r651 r769  
    9696      format.setSampleType(QAudioFormat::UnSignedInt);
    9797
    98       if (QAudioDeviceInfo info(QAudioDeviceInfo::defaultInputDevice());
     98      QAudioDeviceInfo info = QAudioDeviceInfo::defaultInputDevice();
    9999      if (!info.isFormatSupported(format)) {
    100100          qWarning()<<"default format not supported try to use nearest";
     
    147147
    148148    \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.
    149163*/
    150164
     
    191205     All that is required is to open the QIODevice.
    192206
     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
    193220     \sa QIODevice
    194221*/
     
    196223void QAudioInput::start(QIODevice* device)
    197224{
    198     /*
    199        -If currently not StoppedState, stop
    200        -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     */
    205225    d->start(device);
    206226}
     
    211231    directly.
    212232
     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
    213246    \sa QIODevice
    214247*/
     
    216249QIODevice* QAudioInput::start()
    217250{
    218     /*
    219     -If currently not StoppedState, stop
    220     -If no internal QIODevice, create one.
    221     -open audio input.
    222     -If ok, NoError and IdleState, else OpenError and StoppedState
    223     -emit stateChanged()
    224     -return internal QIODevice
    225     */
    226251    return d->start(0);
    227252}
     
    237262
    238263/*!
    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.
    240268*/
    241269
    242270void QAudioInput::stop()
    243271{
    244     /*
    245     -If StoppedState, return
    246     -set to StoppedState
    247     -detach from audio device
    248     -emit stateChanged()
    249     */
    250272    d->stop();
    251273}
     
    257279void QAudioInput::reset()
    258280{
    259     /*
    260     -drop all buffered audio, set buffers to zero.
    261     -call stop()
    262     */
    263281    d->reset();
    264282}
     
    266284/*!
    267285    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.
    268291*/
    269292
    270293void QAudioInput::suspend()
    271294{
    272     /*
    273     -If not ActiveState|IdleState, return
    274     -stop processing audio, saving all buffered audio data
    275     -set NoError and SuspendedState
    276     -emit stateChanged()
    277     */
    278295    d->suspend();
    279296}
     
    281298/*!
    282299    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.
    283305*/
    284306
    285307void QAudioInput::resume()
    286308{
    287     /*
    288     -If SuspendedState, return
    289     -resume audio
    290     -(PULL MODE): set ActiveState, NoError
    291     -(PUSH MODE): set IdleState, NoError
    292     -kick start audio if needed
    293     -emit stateChanged()
    294     */
    295309     d->resume();
    296310}
    297311
    298312/*!
    299     Sets the audio buffer size to \a value milliseconds.
     313    Sets the audio buffer size to \a value bytes.
    300314
    301315    Note: This function can be called anytime before start(), calls to this
     
    312326
    313327/*!
    314     Returns the audio buffer size in milliseconds.
     328    Returns the audio buffer size in bytes.
    315329
    316330    If called before start(), returns platform default value.
     
    328342/*!
    329343    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.
    330347*/
    331348
     
    353370    Sets the interval for notify() signal to be emitted.
    354371    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.
    356376*/
    357377
  • trunk/src/multimedia/audio/qaudioinput_alsa_p.cpp

    r651 r769  
    5959//#define DEBUG_AUDIO 1
    6060
    61 static const int minimumIntervalTime = 50;
    62 
    6361QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
    6462    settings(audioFormat)
     
    122120        if(err < 0)
    123121            reset = true;
     122        else {
     123            bytesAvailable = bytesReady();
     124            if (bytesAvailable <= 0)
     125                reset = true;
     126        }
    124127
    125128    } else if((err == -ESTRPIPE)||(err == -EIO)) {
     
    218221        pullMode = true;
    219222        audioSource = device;
     223        deviceState = QAudio::ActiveState;
    220224    } else {
    221225        //set to push mode
    222226        pullMode = false;
     227        deviceState = QAudio::IdleState;
    223228        audioSource = new InputPrivate(this);
    224229        audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
     
    414419
    415420    errorState  = QAudio::NoError;
    416     deviceState = QAudio::ActiveState;
    417421
    418422    totalTimeValue = 0;
     
    423427void QAudioInputPrivate::close()
    424428{
    425     deviceState = QAudio::StoppedState;
    426429    timer->stop();
    427430
     
    440443        return period_size;
    441444
    442     if(deviceState != QAudio::ActiveState)
     445    if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
    443446        return 0;
    444447    int frames = snd_pcm_avail_update(handle);
     448    if (frames < 0) return frames;
    445449    if((int)frames > (int)buffer_frames)
    446450        frames = buffer_frames;
     
    451455qint64 QAudioInputPrivate::read(char* data, qint64 len)
    452456{
    453     Q_UNUSED(data)
    454457    Q_UNUSED(len)
     458
    455459    // Read in some audio data and write it to QIODevice, pull mode
    456460    if ( !handle )
     
    458462
    459463    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    }
    460478
    461479    int count=0, err = 0;
     
    469487            err = snd_pcm_frames_to_bytes(handle, readFrames);
    470488#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();
    472490#endif
    473491            break;
     
    490508        // got some send it onward
    491509#ifdef DEBUG_AUDIO
    492         qDebug()<<"PULL: frames to write to QIODevice = "<<
     510        qDebug()<<"frames to write to QIODevice = "<<
    493511            snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes";
    494512#endif
    495         if(deviceState != QAudio::ActiveState)
     513        if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
    496514            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
    507539        } else {
    508             totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.frequency();
     540            memcpy(data,audioBuffer,err);
     541            totalTimeValue += err;
    509542            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        }
    514550    }
    515551    return 0;
     
    557593void QAudioInputPrivate::setNotifyInterval(int ms)
    558594{
    559     if(ms >= minimumIntervalTime)
    560         intervalTime = ms;
    561     else
    562         intervalTime = minimumIntervalTime;
     595    intervalTime = qMax(0, ms);
    563596}
    564597
     
    570603qint64 QAudioInputPrivate::processedUSecs() const
    571604{
    572     return totalTimeValue;
     605    qint64 result = qint64(1000000) * totalTimeValue /
     606        (settings.channels()*(settings.sampleSize()/8)) /
     607        settings.frequency();
     608
     609    return result;
    573610}
    574611
     
    608645        return true;
    609646
    610     if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
     647    if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
    611648        emit notify();
    612649        elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
     
    618655qint64 QAudioInputPrivate::elapsedUSecs() const
    619656{
    620     if(!handle)
    621         return 0;
    622 
    623657    if (deviceState == QAudio::StoppedState)
    624658        return 0;
    625659
    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     } else
    644         return 0;
    645 #else
    646660    return clockStamp.elapsed()*1000;
    647 #endif
    648661}
    649662
     
    671684qint64 InputPrivate::readData( char* data, qint64 len)
    672685{
    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);
    710687}
    711688
  • trunk/src/multimedia/audio/qaudioinput_mac_p.cpp

    r651 r769  
    5555#include <QtCore/qdebug.h>
    5656
    57 #include <QtMultimedia/qaudiodeviceinfo.h>
    5857#include <QtMultimedia/qaudioinput.h>
    5958
    6059#include "qaudio_mac_p.h"
    6160#include "qaudioinput_mac_p.h"
    62 
     61#include "qaudiodeviceinfo_mac_p.h"
    6362
    6463QT_BEGIN_NAMESPACE
    6564
    6665
    67 namespace
     66namespace QtMultimediaInternal
    6867{
    6968
     
    170169    void reset()
    171170    {
    172         for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i)
     171        for (UInt32 i = 0; i < bfs->mNumberBuffers; ++i) {
    173172            bfs->mBuffers[i].mDataByteSize = dataSize;
     173            bfs->mBuffers[i].mData = 0;
     174        }
    174175    }
    175176
     
    228229        QObject(parent),
    229230        m_deviceError(false),
     231        m_audioConverter(0),
    230232        m_inputFormat(inputFormat),
    231233        m_outputFormat(outputFormat)
     
    239241        connect(m_flushTimer, SIGNAL(timeout()), SLOT(flushBuffer()));
    240242
    241         if (inputFormat.mSampleRate != outputFormat.mSampleRate) {
     243        if (toQAudioFormat(inputFormat) != toQAudioFormat(outputFormat)) {
    242244            if (AudioConverterNew(&m_inputFormat, &m_outputFormat, &m_audioConverter) != noErr) {
    243245                qWarning() << "QAudioInput: Unable to create an Audio Converter";
     
    518520        errorCode = QAudio::OpenError;
    519521    else {
     522        audioDeviceInfo = new QAudioDeviceInfoInternal(device, QAudio::AudioInput);
    520523        isOpen = false;
    521524        audioDeviceId = AudioDeviceID(did);
     
    524527        totalFrames = 0;
    525528        audioBuffer = 0;
    526         internalBufferSize = default_buffer_size;
     529        internalBufferSize = QtMultimediaInternal::default_buffer_size;
    527530        clockFrequency = AudioGetHostClockFrequency() / 1000;
    528531        errorCode = QAudio::NoError;
     
    538541{
    539542    close();
     543    delete audioDeviceInfo;
    540544}
    541545
     
    575579                               &enable,
    576580                               sizeof(enable)) != noErr) {
    577         qWarning() << "QAudioInput: Unabled to switch to input mode (Enable Input)";
     581        qWarning() << "QAudioInput: Unable to switch to input mode (Enable Input)";
    578582        return false;
    579583    }
     
    586590                            &enable,
    587591                            sizeof(enable)) != noErr) {
    588         qWarning() << "QAudioInput: Unabled to switch to input mode (Disable output)";
     592        qWarning() << "QAudioInput: Unable to switch to input mode (Disable output)";
    589593        return false;
    590594    }
     
    617621
    618622    // Set format
     623    // Wanted
    619624    streamFormat = toAudioStreamBasicDescription(audioFormat);
    620625
    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,
    635630                               kAudioUnitProperty_StreamFormat,
    636631                               kAudioUnitScope_Output,
    637632                               1,
    638633                               &deviceFormat,
    639                                sizeof(streamFormat));
     634                               sizeof(deviceFormat));
    640635    }
    641636    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        }
    648657    }
    649658
     
    662671
    663672    // Allocate buffer
    664     periodSizeBytes = (numberOfFrames * streamFormat.mSampleRate / deviceFormat.mSampleRate) *
    665                         streamFormat.mBytesPerFrame;
     673    periodSizeBytes = numberOfFrames * streamFormat.mBytesPerFrame;
     674
    666675    if (internalBufferSize < periodSizeBytes * 2)
    667676        internalBufferSize = periodSizeBytes * 2;
     
    669678        internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame;
    670679
    671     audioBuffer = new QAudioInputBuffer(internalBufferSize,
     680    audioBuffer = new QtMultimediaInternal::QAudioInputBuffer(internalBufferSize,
    672681                                        periodSizeBytes,
    673682                                        deviceFormat,
     
    675684                                        this);
    676685
    677     audioIO = new MacInputDevice(audioBuffer, this);
     686    audioIO = new QtMultimediaInternal::MacInputDevice(audioBuffer, this);
    678687
    679688    // Init
     
    708717    QIODevice*  op = device;
    709718
    710     if (!open()) {
     719    if (!audioFormat.isValid() || !open()) {
    711720        stateCode = QAudio::StoppedState;
    712721        errorCode = QAudio::OpenError;
     
    805814void QAudioInputPrivate::setNotifyInterval(int milliSeconds)
    806815{
     816    if (intervalTimer->interval() == milliSeconds)
     817        return;
     818
     819    if (milliSeconds <= 0)
     820        milliSeconds = 0;
     821
    807822    intervalTimer->setInterval(milliSeconds);
    808823}
     
    884899{
    885900    audioBuffer->startFlushTimer();
    886     intervalTimer->start();
     901    if (intervalTimer->interval() > 0)
     902        intervalTimer->start();
    887903}
    888904
  • trunk/src/multimedia/audio/qaudioinput_mac_p.h

    r651 r769  
    7575class QTimer;
    7676class QIODevice;
     77class QAbstractAudioDeviceInfo;
    7778
    78 namespace
     79namespace QtMultimediaInternal
    7980{
    8081class QAudioInputBuffer;
     
    9899    QAudio::Error   errorCode;
    99100    QAudio::State   stateCode;
    100     QAudioInputBuffer*   audioBuffer;
     101    QtMultimediaInternal::QAudioInputBuffer*   audioBuffer;
    101102    QMutex          mutex;
    102103    QWaitCondition  threadFinished;
     
    105106    AudioStreamBasicDescription streamFormat;
    106107    AudioStreamBasicDescription deviceFormat;
     108    QAbstractAudioDeviceInfo *audioDeviceInfo;
    107109
    108110    QAudioInputPrivate(const QByteArray& device, QAudioFormat const& format);
  • trunk/src/multimedia/audio/qaudioinput_win32_p.cpp

    r651 r769  
    5757
    5858//#define DEBUG_AUDIO 1
    59 
    60 static CRITICAL_SECTION waveInCriticalSection;
    61 
    62 static const int minimumIntervalTime = 50;
    6359
    6460QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
     
    7773    resuming = false;
    7874    finished = false;
    79 
    80     connect(this,SIGNAL(processMore()),SLOT(deviceReady()));
    81 
    82     InitializeCriticalSection(&waveInCriticalSection);
    8375}
    8476
     
    8678{
    8779    stop();
    88     DeleteCriticalSection(&waveInCriticalSection);
    8980}
    9081
     
    10192        return;
    10293
     94    QMutexLocker(&qAudio->mutex);
     95
    10396    switch(uMsg) {
    10497        case WIM_OPEN:
    10598            break;
    10699        case WIM_DATA:
    107             EnterCriticalSection(&waveInCriticalSection);
    108100            if(qAudio->waveFreeBlockCount > 0)
    109101                qAudio->waveFreeBlockCount--;
    110102            qAudio->feedback();
    111             LeaveCriticalSection(&waveInCriticalSection);
    112103            break;
    113104        case WIM_CLOSE:
    114             EnterCriticalSection(&waveInCriticalSection);
    115105            qAudio->finished = true;
    116             LeaveCriticalSection(&waveInCriticalSection);
    117106            break;
    118107        default:
     
    159148
    160149    for(int i = 0; i < count; i++) {
    161         waveInUnprepareHeader(hWaveIn,&blocks[i], sizeof(WAVEHDR));
     150        waveInUnprepareHeader(hWaveIn,blocks, sizeof(WAVEHDR));
    162151        blocks+=sizeof(WAVEHDR);
    163152    }
     
    193182        pullMode = true;
    194183        audioSource = device;
     184        deviceState = QAudio::ActiveState;
    195185    } else {
    196186        //set to push mode
    197187        pullMode = false;
     188        deviceState = QAudio::IdleState;
    198189        audioSource = new InputPrivate(this);
    199190        audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
     
    225216    header = 0;
    226217    if(buffer_size == 0) {
    227         // Default buffer size, 100ms, default period size is 20ms
    228         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;
    229220        period_size = buffer_size/5;
    230221    } else {
     
    279270    }
    280271
    281     EnterCriticalSection(&waveInCriticalSection);
     272    mutex.lock();
    282273    waveFreeBlockCount = buffer_size/period_size;
    283     LeaveCriticalSection(&waveInCriticalSection);
     274    mutex.unlock();
    284275
    285276    waveCurrentBlock = 0;
     
    307298    totalTimeValue = 0;
    308299    errorState  = QAudio::NoError;
    309     deviceState = QAudio::ActiveState;
    310300    return true;
    311301}
     
    316306        return;
    317307
     308    deviceState = QAudio::StoppedState;
    318309    waveInReset(hWaveIn);
    319310    waveInClose(hWaveIn);
    320     deviceState = QAudio::StoppedState;
    321311
    322312    int count = 0;
     
    326316    }
    327317
    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));
    334321    freeBlocks(waveBlocks);
     322    mutex.unlock();
    335323}
    336324
     
    353341    qint64 l = 0;
    354342    qint64 written = 0;
    355 
    356343    while(!done) {
    357344        // Read in some audio data
     
    374361
    375362                } else {
    376                     totalTimeValue += waveBlocks[header].dwBytesRecorded
    377                         /((settings.channels()*settings.sampleSize()/8))
    378                         *10000/settings.frequency()*100;
     363                    totalTimeValue += waveBlocks[header].dwBytesRecorded;
    379364                    errorState = QAudio::NoError;
    380                     deviceState = QAudio::ActiveState;
     365                    if (deviceState != QAudio::ActiveState) {
     366                        deviceState = QAudio::ActiveState;
     367                        emit stateChanged(deviceState);
     368                    }
    381369                    resuming = false;
    382370                }
     
    388376                qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l;
    389377#endif
    390                 totalTimeValue += waveBlocks[header].dwBytesRecorded
    391                     /((settings.channels()*settings.sampleSize()/8))
    392                     *10000/settings.frequency()*100;
     378                totalTimeValue += waveBlocks[header].dwBytesRecorded;
    393379                errorState = QAudio::NoError;
    394                 deviceState = QAudio::ActiveState;
     380                if (deviceState != QAudio::ActiveState) {
     381                    deviceState = QAudio::ActiveState;
     382                    emit stateChanged(deviceState);
     383                }
    395384                resuming = false;
    396385            }
    397386        } else {
    398387            //no data, not ready yet, next time
    399             return 0;
     388            break;
    400389        }
    401390
    402391        waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
    403392
    404         EnterCriticalSection(&waveInCriticalSection);
     393        mutex.lock();
    405394        waveFreeBlockCount++;
    406         LeaveCriticalSection(&waveInCriticalSection);
     395        mutex.unlock();
     396
    407397        waveBlocks[header].dwBytesRecorded=0;
    408398        waveBlocks[header].dwFlags = 0L;
     
    412402            qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result);
    413403            errorState = QAudio::IOError;
    414             EnterCriticalSection(&waveInCriticalSection);
     404
     405            mutex.lock();
    415406            waveFreeBlockCount--;
    416             LeaveCriticalSection(&waveInCriticalSection);
     407            mutex.unlock();
     408
    417409            return 0;
    418410        }
     
    421413            qWarning("QAudioInput: failed to setup block %d,err=%d",header,result);
    422414            errorState = QAudio::IOError;
    423             EnterCriticalSection(&waveInCriticalSection);
     415
     416            mutex.lock();
    424417            waveFreeBlockCount--;
    425             LeaveCriticalSection(&waveInCriticalSection);
     418            mutex.unlock();
     419
    426420            return 0;
    427421        }
     
    431425        p+=l;
    432426
    433         EnterCriticalSection(&waveInCriticalSection);
     427        mutex.lock();
    434428        if(!pullMode) {
    435429            if(l+period_size > len && waveFreeBlockCount == buffer_size/period_size)
     
    439433                done = true;
    440434        }
    441         LeaveCriticalSection(&waveInCriticalSection);
     435        mutex.unlock();
    442436
    443437        written+=l;
     
    463457            }
    464458        }
    465         EnterCriticalSection(&waveInCriticalSection);
     459
     460        mutex.lock();
    466461        waveFreeBlockCount = buffer_size/period_size;
    467         LeaveCriticalSection(&waveInCriticalSection);
     462        mutex.unlock();
    468463
    469464        waveCurrentBlock = 0;
     
    493488void QAudioInputPrivate::setNotifyInterval(int ms)
    494489{
    495     if(ms >= minimumIntervalTime)
    496         intervalTime = ms;
    497     else
    498         intervalTime = minimumIntervalTime;
     490    intervalTime = qMax(0, ms);
    499491}
    500492
     
    506498qint64 QAudioInputPrivate::processedUSecs() const
    507499{
    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;
    509507}
    510508
     
    524522    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT "<<this;
    525523#endif
     524    if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState))
     525        QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection);
     526}
     527
     528bool QAudioInputPrivate::deviceReady()
     529{
    526530    bytesAvailable = bytesReady();
    527 
    528     if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState))
    529         emit processMore();
    530 }
    531 
    532 bool QAudioInputPrivate::deviceReady()
    533 {
    534531#ifdef DEBUG_AUDIO
    535532    QTime now(QTime::currentTime());
    536533    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT";
    537534#endif
     535    if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
     536        return true;
     537
    538538    if(pullMode) {
    539539        // reads some audio data and writes it to QIODevice
     
    544544        a->trigger();
    545545    }
    546     if(deviceState != QAudio::ActiveState)
    547         return true;
    548 
    549     if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
     546
     547    if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
    550548        emit notify();
    551549        elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
     
    578576{
    579577    // push mode, user read() called
    580     if(audioDevice->deviceState != QAudio::ActiveState)
     578    if(audioDevice->deviceState != QAudio::ActiveState &&
     579            audioDevice->deviceState != QAudio::IdleState)
    581580        return 0;
    582581    // Read in some audio data
  • trunk/src/multimedia/audio/qaudioinput_win32_p.h

    r651 r769  
    6363#include <QtCore/qstringlist.h>
    6464#include <QtCore/qdatetime.h>
     65#include <QtCore/qmutex.h>
    6566
    6667#include <QtMultimedia/qaudio.h>
     
    123124    int waveCurrentBlock;
    124125
     126    QMutex mutex;
     127
    125128    static void CALLBACK waveInProc( HWAVEIN hWaveIn, UINT uMsg,
    126129            DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );
  • trunk/src/multimedia/audio/qaudiooutput.cpp

    r651 r769  
    203203    All that is required is to open the QIODevice.
    204204
     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
    205216    \sa QIODevice
    206217*/
     
    208219void QAudioOutput::start(QIODevice* device)
    209220{
    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 StoppedState
    215     -emit stateChanged()
    216     */
    217221    d->start(device);
    218222}
     
    222226    transfer. This QIODevice can be used to write() audio data directly.
    223227
     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
    224239    \sa QIODevice
    225240*/
     
    227242QIODevice* QAudioOutput::start()
    228243{
    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 StoppedState
    234     -emit stateChanged()
    235     -return internal QIODevice
    236     */
    237244    return d->start(0);
    238245}
    239246
    240247/*!
    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.
    242252*/
    243253
    244254void QAudioOutput::stop()
    245255{
    246     /*
    247     -If StoppedState, return
    248     -set to StoppedState
    249     -detach from audio device
    250     -emit stateChanged()
    251     */
    252256    d->stop();
    253257}
     
    259263void QAudioOutput::reset()
    260264{
    261     /*
    262     -drop all buffered audio, set buffers to zero.
    263     -call stop()
    264     */
    265265    d->reset();
    266266}
     
    268268/*!
    269269    Stops processing audio data, preserving buffered audio data.
     270
     271    Sets error() to QAudio::NoError, state() to QAudio::SuspendedState and
     272    emit stateChanged() signal.
    270273*/
    271274
    272275void QAudioOutput::suspend()
    273276{
    274     /*
    275     -If not ActiveState|IdleState, return
    276     -stop processing audio, saving all buffered audio data
    277     -set NoError and SuspendedState
    278     -emit stateChanged()
    279     */
    280277    d->suspend();
    281278}
     
    283280/*!
    284281    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.
    285289*/
    286290
    287291void QAudioOutput::resume()
    288292{
    289     /*
    290     -If SuspendedState, return
    291     -resume audio
    292     -(PULL MODE): set ActiveState, NoError
    293     -(PUSH MODE): set IdleState, NoError
    294     -kick start audio if needed
    295     -emit stateChanged()
    296     */
    297293     d->resume();
    298294}
     
    300296/*!
    301297    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.
    302301*/
    303302
    304303int QAudioOutput::bytesFree() const
    305304{
    306     /*
    307     -If not ActiveState|IdleState, return 0
    308     -return space available in audio buffer in bytes
    309     */
    310305    return d->bytesFree();
    311306}
     
    354349    Sets the interval for notify() signal to be emitted.
    355350    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.
    357355*/
    358356
     
    372370
    373371/*!
    374     Returns the amount of audio data processed since start()
     372    Returns the amount of audio data processed by the class since start()
    375373    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
    376383*/
    377384
  • trunk/src/multimedia/audio/qaudiooutput_alsa_p.cpp

    r651 r769  
    5959//#define DEBUG_AUDIO 1
    6060
    61 static const int minimumIntervalTime = 50;
    62 
    6361QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
    6462    settings(audioFormat)
     
    8583    opened = false;
    8684
    87     QStringList list1 = QString(QLatin1String(device)).split(QLatin1String(":"));
    88     m_device = QByteArray(list1.at(0).toLocal8Bit().constData());
     85    m_device = device;
    8986
    9087    timer = new QTimer(this);
     
    260257    if(deviceState == QAudio::StoppedState)
    261258        return;
     259    errorState = QAudio::NoError;
    262260    deviceState = QAudio::StoppedState;
    263261    close();
     
    282280    unsigned int freakuency=settings.frequency();
    283281
    284     QString dev = QLatin1String(m_device.constData());
     282    QString dev = QString(QLatin1String(m_device.constData()));
    285283    QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioOutput);
    286284    if(dev.compare(QLatin1String("default")) == 0) {
    287285#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
    288         dev = QLatin1String(devices.first().constData());
     286        dev = QLatin1String(devices.first());
    289287#else
    290288        dev = QLatin1String("hw:0,0");
     
    369367    }
    370368    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 ) {
    371411        err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
    372412        if ( err < 0 ) {
    373413            fatal = true;
    374                 errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err);
     414            errMessage = QString::fromLatin1("QAudioOutput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err);
    375415        }
    376416    }
     
    443483void QAudioOutputPrivate::close()
    444484{
    445     deviceState = QAudio::StoppedState;
    446485    timer->stop();
    447486
     
    495534    }
    496535    if(err > 0) {
    497         totalTimeValue += err*1000000/settings.frequency();
     536        totalTimeValue += err;
    498537        resuming = false;
    499538        errorState = QAudio::NoError;
    500         deviceState = QAudio::ActiveState;
     539        if (deviceState != QAudio::ActiveState) {
     540            deviceState = QAudio::ActiveState;
     541            emit stateChanged(deviceState);
     542        }
    501543        return snd_pcm_frames_to_bytes( handle, err );
    502544    } else
     
    530572void QAudioOutputPrivate::setNotifyInterval(int ms)
    531573{
    532     if(ms >= minimumIntervalTime)
    533         intervalTime = ms;
    534     else
    535         intervalTime = minimumIntervalTime;
     574    intervalTime = qMax(0, ms);
    536575}
    537576
     
    543582qint64 QAudioOutputPrivate::processedUSecs() const
    544583{
    545     return totalTimeValue;
     584    return qint64(1000000) * totalTimeValue / settings.frequency();
    546585}
    547586
     
    563602        }
    564603        resuming = true;
    565         if(pullMode)
    566             deviceState = QAudio::ActiveState;
    567         else
    568             deviceState = QAudio::IdleState;
     604
     605        deviceState = QAudio::ActiveState;
    569606
    570607        errorState = QAudio::NoError;
     
    605642void QAudioOutputPrivate::feedback()
    606643{
    607     QMetaObject::invokeMethod(this, SLOT(updateAvailable()), Qt::QueuedConnection);
    608 }
     644    updateAvailable();
     645}
     646
    609647
    610648void QAudioOutputPrivate::updateAvailable()
     
    638676            if(deviceState != QAudio::ActiveState)
    639677                return true;
    640             write(audioBuffer,l);
     678            qint64 bytesWritten = write(audioBuffer,l);
     679            if (bytesWritten != l)
     680                audioSource->seek(audioSource->pos()-(l-bytesWritten));
    641681            bytesAvailable = bytesFree();
    642682
     
    646686            if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) {
    647687                // 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) {
    648706                errorState = QAudio::UnderrunError;
    649707                deviceState = QAudio::IdleState;
    650708                emit stateChanged(deviceState);
    651709            }
    652 
    653         } else if(l < 0) {
    654             close();
    655             errorState = QAudio::IOError;
    656             emit stateChanged(deviceState);
    657         }
    658     } else
    659         bytesAvailable = bytesFree();
     710        }
     711    }
    660712
    661713    if(deviceState != QAudio::ActiveState)
    662714        return true;
    663715
    664     if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
     716    if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
    665717        emit notify();
    666718        elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
     
    672724qint64 QAudioOutputPrivate::elapsedUSecs() const
    673725{
    674     if(!handle)
    675         return 0;
    676 
    677726    if (deviceState == QAudio::StoppedState)
    678727        return 0;
    679728
    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     } else
    698         return 0;
    699 #else
    700729    return clockStamp.elapsed()*1000;
    701 #endif
    702     return 0;
    703730}
    704731
  • trunk/src/multimedia/audio/qaudiooutput_mac_p.cpp

    r651 r769  
    7171
    7272
    73 namespace
     73namespace QtMultimediaInternal
    7474{
    7575
     
    238238
    239239public:
    240     MacOutputDevice(QAudioOutputBuffer* audioBuffer, QObject* parent):
     240    MacOutputDevice(QtMultimediaInternal::QAudioOutputBuffer* audioBuffer, QObject* parent):
    241241        QIODevice(parent),
    242242        m_audioBuffer(audioBuffer)
     
    264264
    265265private:
    266     QAudioOutputBuffer*    m_audioBuffer;
     266    QtMultimediaInternal::QAudioOutputBuffer*    m_audioBuffer;
    267267};
    268268
     
    286286        totalFrames = 0;
    287287        audioBuffer = 0;
    288         internalBufferSize = default_buffer_size;
     288        internalBufferSize = QtMultimediaInternal::default_buffer_size;
    289289        clockFrequency = AudioGetHostClockFrequency() / 1000;
    290290        errorCode = QAudio::NoError;
     
    400400        internalBufferSize -= internalBufferSize % streamFormat.mBytesPerFrame;
    401401
    402     audioBuffer = new QAudioOutputBuffer(internalBufferSize, periodSizeBytes, audioFormat);
     402    audioBuffer = new QtMultimediaInternal::QAudioOutputBuffer(internalBufferSize, periodSizeBytes, audioFormat);
    403403    connect(audioBuffer, SIGNAL(readyRead()), SLOT(inputReady()));  // Pull
    404404
     
    436436    QIODevice*  op = device;
    437437
    438     if (!open()) {
     438    if (!audioFormat.isValid() || !open()) {
    439439        stateCode = QAudio::StoppedState;
    440440        errorCode = QAudio::OpenError;
     
    537537void QAudioOutputPrivate::setNotifyInterval(int milliSeconds)
    538538{
     539    if (intervalTimer->interval() == milliSeconds)
     540        return;
     541
     542    if (milliSeconds <= 0)
     543        milliSeconds = 0;
     544
    539545    intervalTimer->setInterval(milliSeconds);
    540546}
     
    623629{
    624630    audioBuffer->startFillTimer();
    625     intervalTimer->start();
     631    if (intervalTimer->interval() > 0)
     632        intervalTimer->start();
    626633}
    627634
  • trunk/src/multimedia/audio/qaudiooutput_mac_p.h

    r651 r769  
    7575class QIODevice;
    7676
    77 namespace
     77namespace QtMultimediaInternal
    7878{
    7979class QAudioOutputBuffer;
     
    9797    AudioStreamBasicDescription deviceFormat;
    9898    AudioStreamBasicDescription streamFormat;
    99     QAudioOutputBuffer*   audioBuffer;
     99    QtMultimediaInternal::QAudioOutputBuffer*   audioBuffer;
    100100    QAtomicInt      audioThreadState;
    101101    QWaitCondition  threadFinished;
  • trunk/src/multimedia/audio/qaudiooutput_win32_p.cpp

    r651 r769  
    5656
    5757QT_BEGIN_NAMESPACE
    58 
    59 static CRITICAL_SECTION waveOutCriticalSection;
    60 
    61 static const int minimumIntervalTime = 50;
    6258
    6359QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
     
    7672    pullMode = true;
    7773    finished = false;
    78     InitializeCriticalSection(&waveOutCriticalSection);
    7974}
    8075
    8176QAudioOutputPrivate::~QAudioOutputPrivate()
    8277{
    83     EnterCriticalSection(&waveOutCriticalSection);
     78    mutex.lock();
    8479    finished = true;
    85     LeaveCriticalSection(&waveOutCriticalSection);
     80    mutex.unlock();
    8681
    8782    close();
    88     DeleteCriticalSection(&waveOutCriticalSection);
    8983}
    9084
     
    10094    if(!qAudio)
    10195        return;
     96
     97    QMutexLocker(&qAudio->mutex);
    10298
    10399    switch(uMsg) {
     
    108104            return;
    109105        case WOM_DONE:
    110             EnterCriticalSection(&waveOutCriticalSection);
    111106            if(qAudio->finished || qAudio->buffer_size == 0 || qAudio->period_size == 0) {
    112                 LeaveCriticalSection(&waveOutCriticalSection);
    113107                return;
    114108            }
     
    117111                qAudio->waveFreeBlockCount = qAudio->buffer_size/qAudio->period_size;
    118112            qAudio->feedback();
    119             LeaveCriticalSection(&waveOutCriticalSection);
    120113            break;
    121114        default:
     
    153146
    154147    for(int i = 0; i < count; i++) {
    155         waveOutUnprepareHeader(hWaveOut,&blocks[i], sizeof(WAVEHDR));
     148        waveOutUnprepareHeader(hWaveOut,blocks, sizeof(WAVEHDR));
    156149        blocks+=sizeof(WAVEHDR);
    157150    }
     
    212205    qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
    213206#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    }
    214214    if(buffer_size == 0) {
    215215        // Default buffer size, 200ms, default period size is 40ms
     
    221221    waveBlocks = allocateBlocks(period_size, buffer_size/period_size);
    222222
    223     EnterCriticalSection(&waveOutCriticalSection);
     223    mutex.lock();
    224224    waveFreeBlockCount = buffer_size/period_size;
    225     LeaveCriticalSection(&waveOutCriticalSection);
     225    mutex.unlock();
    226226
    227227    waveCurrentBlock = 0;
     
    290290
    291291    deviceState = QAudio::StoppedState;
     292    errorState = QAudio::NoError;
    292293    int delay = (buffer_size-bytesFree())*1000/(settings.frequency()
    293294                  *settings.channels()*(settings.sampleSize()/8));
     
    328329void QAudioOutputPrivate::setNotifyInterval(int ms)
    329330{
    330     if(ms >= minimumIntervalTime)
    331         intervalTime = ms;
    332     else
    333         intervalTime = minimumIntervalTime;
     331    intervalTime = qMax(0, ms);
    334332}
    335333
     
    341339qint64 QAudioOutputPrivate::processedUSecs() const
    342340{
    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;
    344348}
    345349
     
    347351{
    348352    // Write out some audio data
     353    if (deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
     354        return 0;
    349355
    350356    char* p = (char*)data;
     
    355361    current = &waveBlocks[waveCurrentBlock];
    356362    while(l > 0) {
    357         EnterCriticalSection(&waveOutCriticalSection);
     363        mutex.lock();
    358364        if(waveFreeBlockCount==0) {
    359             LeaveCriticalSection(&waveOutCriticalSection);
     365            mutex.unlock();
    360366            break;
    361367        }
    362         LeaveCriticalSection(&waveOutCriticalSection);
     368        mutex.unlock();
    363369
    364370        if(current->dwFlags & WHDR_PREPARED)
     
    377383        waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));
    378384
    379         EnterCriticalSection(&waveOutCriticalSection);
     385        mutex.lock();
    380386        waveFreeBlockCount--;
    381         LeaveCriticalSection(&waveOutCriticalSection);
    382387#ifdef DEBUG_AUDIO
    383         EnterCriticalSection(&waveOutCriticalSection);
    384388        qDebug("write out l=%d, waveFreeBlockCount=%d",
    385389                current->dwBufferLength,waveFreeBlockCount);
    386         LeaveCriticalSection(&waveOutCriticalSection);
    387390#endif
    388         totalTimeValue += current->dwBufferLength
    389             /(settings.channels()*(settings.sampleSize()/8))
    390             *1000000/settings.frequency();;
     391        mutex.unlock();
     392        totalTimeValue += current->dwBufferLength;
    391393        waveCurrentBlock++;
    392394        waveCurrentBlock %= buffer_size/period_size;
    393395        current = &waveBlocks[waveCurrentBlock];
    394396        current->dwUser = 0;
     397        errorState = QAudio::NoError;
     398        if (deviceState != QAudio::ActiveState) {
     399            deviceState = QAudio::ActiveState;
     400            emit stateChanged(deviceState);
     401        }
    395402    }
    396403    return (len-l);
     
    410417void QAudioOutputPrivate::suspend()
    411418{
    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));
    413422        waveOutPause(hWaveOut);
     423        Sleep(delay+10);
    414424        deviceState = QAudio::SuspendedState;
    415425        errorState = QAudio::NoError;
     
    434444bool QAudioOutputPrivate::deviceReady()
    435445{
     446    if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState)
     447        return false;
     448
    436449    if(pullMode) {
    437450        int chunks = bytesAvailable/period_size;
     
    445458
    446459        bool full=false;
    447         EnterCriticalSection(&waveOutCriticalSection);
     460
     461        mutex.lock();
    448462        if(waveFreeBlockCount==0) full = true;
    449         LeaveCriticalSection(&waveOutCriticalSection);
     463        mutex.unlock();
     464
    450465        if (full){
    451466#ifdef DEBUG_AUDIO
    452467            qDebug() << "Skipping data as unable to write";
    453468#endif
    454             if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) {
     469            if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime ) {
    455470                emit notify();
    456471                elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
     
    466481        if(l > 0) {
    467482            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            }
    470493            if(startup)
    471494                waveOutRestart(hWaveOut);
     
    474497
    475498            int check = 0;
    476             EnterCriticalSection(&waveOutCriticalSection);
     499
     500            mutex.lock();
    477501            check = waveFreeBlockCount;
    478             LeaveCriticalSection(&waveOutCriticalSection);
     502            mutex.unlock();
     503
    479504            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) {
    480525                errorState = QAudio::UnderrunError;
    481526                deviceState = QAudio::IdleState;
    482527                emit stateChanged(deviceState);
    483528            }
    484 
    485         } else if(l < 0) {
    486             bytesAvailable = bytesFree();
    487             errorState = QAudio::IOError;
    488529        }
    489530    }
    490     if(deviceState != QAudio::ActiveState)
     531    if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
    491532        return true;
    492533
    493     if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
     534    if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
    494535        emit notify();
    495536        elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
  • trunk/src/multimedia/audio/qaudiooutput_win32_p.h

    r651 r769  
    6262#include <QtCore/qstringlist.h>
    6363#include <QtCore/qdatetime.h>
     64#include <QtCore/qmutex.h>
    6465
    6566#include <QtMultimedia/qaudio.h>
     
    120121            DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );
    121122
     123    QMutex mutex;
     124
    122125    WAVEHDR* allocateBlocks(int size, int count);
    123126    void freeBlocks(WAVEHDR* blockArray);
  • trunk/src/multimedia/video/qabstractvideobuffer.cpp

    r651 r769  
    4949    \class QAbstractVideoBuffer
    5050    \brief The QAbstractVideoBuffer class is an abstraction for video data.
    51     \preliminary
    5251    \since 4.6
    5352
  • trunk/src/multimedia/video/qabstractvideosurface.cpp

    r651 r769  
    4747    \class QAbstractVideoSurface
    4848    \brief The QAbstractVideoSurface class is a base class for video presentation surfaces.
    49     \preliminary
    5049    \since 4.6
    5150
  • trunk/src/multimedia/video/qvideoframe.cpp

    r651 r769  
    103103    \class QVideoFrame
    104104    \brief The QVideoFrame class provides a representation of a frame of video data.
    105     \preliminary
    106105    \since 4.6
    107106
  • trunk/src/multimedia/video/qvideosurfaceformat.cpp

    r651 r769  
    137137    \brief The QVideoSurfaceFormat class specifies the stream format of a video presentation
    138138    surface.
    139     \preliminary
    140139    \since 4.6
    141140
Note: See TracChangeset for help on using the changeset viewer.