qtmobility/src/multimedia/audio/qaudioinput_win32_p.cpp
changeset 14 6fbed849b4f4
equal deleted inserted replaced
11:06b8e2af4411 14:6fbed849b4f4
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 //
       
    43 //  W A R N I N G
       
    44 //  -------------
       
    45 //
       
    46 // This file is not part of the Qt API.  It exists for the convenience
       
    47 // of other Qt classes.  This header file may change from version to
       
    48 // version without notice, or even be removed.
       
    49 //
       
    50 // We mean it.
       
    51 //
       
    52 
       
    53 
       
    54 #include "qaudioinput_win32_p.h"
       
    55 
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 //#define DEBUG_AUDIO 1
       
    59 
       
    60 QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device)
       
    61 {
       
    62     bytesAvailable = 0;
       
    63     buffer_size = 0;
       
    64     period_size = 0;
       
    65     m_device = device;
       
    66     totalTimeValue = 0;
       
    67     intervalTime = 1000;
       
    68     errorState = QAudio::NoError;
       
    69     deviceState = QAudio::StoppedState;
       
    70     audioSource = 0;
       
    71     pullMode = true;
       
    72     resuming = false;
       
    73     finished = false;
       
    74 }
       
    75 
       
    76 QAudioInputPrivate::~QAudioInputPrivate()
       
    77 {
       
    78     stop();
       
    79 }
       
    80 
       
    81 void QT_WIN_CALLBACK QAudioInputPrivate::waveInProc( HWAVEIN hWaveIn, UINT uMsg,
       
    82         DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 )
       
    83 {
       
    84     Q_UNUSED(dwParam1)
       
    85     Q_UNUSED(dwParam2)
       
    86     Q_UNUSED(hWaveIn)
       
    87 
       
    88     QAudioInputPrivate* qAudio;
       
    89     qAudio = (QAudioInputPrivate*)(dwInstance);
       
    90     if(!qAudio)
       
    91         return;
       
    92 
       
    93     QMutexLocker(&qAudio->mutex);
       
    94 
       
    95     switch(uMsg) {
       
    96         case WIM_OPEN:
       
    97             break;
       
    98         case WIM_DATA:
       
    99             if(qAudio->waveFreeBlockCount > 0)
       
   100                 qAudio->waveFreeBlockCount--;
       
   101             qAudio->feedback();
       
   102             break;
       
   103         case WIM_CLOSE:
       
   104             qAudio->finished = true;
       
   105             break;
       
   106         default:
       
   107             return;
       
   108     }
       
   109 }
       
   110 
       
   111 WAVEHDR* QAudioInputPrivate::allocateBlocks(int size, int count)
       
   112 {
       
   113     int i;
       
   114     unsigned char* buffer;
       
   115     WAVEHDR* blocks;
       
   116     DWORD totalBufferSize = (size + sizeof(WAVEHDR))*count;
       
   117 
       
   118     if((buffer=(unsigned char*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
       
   119                     totalBufferSize)) == 0) {
       
   120         qWarning("QAudioInput: Memory allocation error");
       
   121         return 0;
       
   122     }
       
   123     blocks = (WAVEHDR*)buffer;
       
   124     buffer += sizeof(WAVEHDR)*count;
       
   125     for(i = 0; i < count; i++) {
       
   126         blocks[i].dwBufferLength = size;
       
   127         blocks[i].lpData = (LPSTR)buffer;
       
   128         blocks[i].dwBytesRecorded=0;
       
   129         blocks[i].dwUser = 0L;
       
   130         blocks[i].dwFlags = 0L;
       
   131         blocks[i].dwLoops = 0L;
       
   132         result = waveInPrepareHeader(hWaveIn,&blocks[i], sizeof(WAVEHDR));
       
   133         if(result != MMSYSERR_NOERROR) {
       
   134             qWarning("QAudioInput: Can't prepare block %d",i);
       
   135             return 0;
       
   136         }
       
   137         buffer += size;
       
   138     }
       
   139     return blocks;
       
   140 }
       
   141 
       
   142 void QAudioInputPrivate::freeBlocks(WAVEHDR* blockArray)
       
   143 {
       
   144     WAVEHDR* blocks = blockArray;
       
   145 
       
   146     int count = buffer_size/period_size;
       
   147 
       
   148     for(int i = 0; i < count; i++) {
       
   149         waveInUnprepareHeader(hWaveIn,blocks, sizeof(WAVEHDR));
       
   150         blocks+=sizeof(WAVEHDR);
       
   151     }
       
   152     HeapFree(GetProcessHeap(), 0, blockArray);
       
   153 }
       
   154 
       
   155 QAudio::Error QAudioInputPrivate::error() const
       
   156 {
       
   157     return errorState;
       
   158 }
       
   159 
       
   160 QAudio::State QAudioInputPrivate::state() const
       
   161 {
       
   162     return deviceState;
       
   163 }
       
   164 
       
   165 void QAudioInputPrivate::setFormat(const QAudioFormat& fmt)
       
   166 {
       
   167     if (deviceState == QAudio::StoppedState)
       
   168         settings = fmt;
       
   169 }
       
   170 
       
   171 QAudioFormat QAudioInputPrivate::format() const
       
   172 {
       
   173     return settings;
       
   174 }
       
   175 
       
   176 void QAudioInputPrivate::start(QIODevice* device)
       
   177 {
       
   178     if(deviceState != QAudio::StoppedState)
       
   179         close();
       
   180 
       
   181     if(!pullMode && audioSource)
       
   182         delete audioSource;
       
   183 
       
   184     pullMode = true;
       
   185     audioSource = device;
       
   186 
       
   187     deviceState = QAudio::ActiveState;
       
   188 
       
   189     if(!open())
       
   190         return;
       
   191 
       
   192     emit stateChanged(deviceState);
       
   193 }
       
   194 
       
   195 QIODevice* QAudioInputPrivate::start()
       
   196 {
       
   197     if(deviceState != QAudio::StoppedState)
       
   198         close();
       
   199 
       
   200     if(!pullMode && audioSource)
       
   201         delete audioSource;
       
   202 
       
   203     pullMode = false;
       
   204     audioSource = new InputPrivate(this);
       
   205     audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
       
   206 
       
   207     deviceState = QAudio::IdleState;
       
   208 
       
   209     if(!open())
       
   210         return 0;
       
   211 
       
   212     emit stateChanged(deviceState);
       
   213 
       
   214     return audioSource;
       
   215 }
       
   216 
       
   217 void QAudioInputPrivate::stop()
       
   218 {
       
   219     if(deviceState == QAudio::StoppedState)
       
   220         return;
       
   221 
       
   222     close();
       
   223     emit stateChanged(deviceState);
       
   224 }
       
   225 
       
   226 bool QAudioInputPrivate::open()
       
   227 {
       
   228 #ifdef DEBUG_AUDIO
       
   229     QTime now(QTime::currentTime());
       
   230     qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
       
   231 #endif
       
   232     header = 0;
       
   233     if(buffer_size == 0) {
       
   234         // Default buffer size, 200ms, default period size is 40ms
       
   235         buffer_size = settings.frequency()*settings.channels()*(settings.sampleSize()/8)*0.2;
       
   236 	period_size = buffer_size/5;
       
   237     } else {
       
   238         period_size = buffer_size/5;
       
   239     }
       
   240 #ifdef Q_OS_WINCE
       
   241     // For wince reduce size to 40ms for buffer size and 20ms period
       
   242     buffer_size = settings.sampleRate()*settings.channelCount()*(settings.sampleSize()/8)*0.04;
       
   243     period_size = buffer_size/2;
       
   244 #endif
       
   245     timeStamp.restart();
       
   246     elapsedTimeOffset = 0;
       
   247     wfx.nSamplesPerSec = settings.frequency();
       
   248     wfx.wBitsPerSample = settings.sampleSize();
       
   249     wfx.nChannels = settings.channels();
       
   250     wfx.cbSize = 0;
       
   251 
       
   252     wfx.wFormatTag = WAVE_FORMAT_PCM;
       
   253     wfx.nBlockAlign = (wfx.wBitsPerSample >> 3) * wfx.nChannels;
       
   254     wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
       
   255 
       
   256     UINT_PTR devId = WAVE_MAPPER;
       
   257 
       
   258     WAVEINCAPS wic;
       
   259     unsigned long iNumDevs,ii;
       
   260     iNumDevs = waveInGetNumDevs();
       
   261     for(ii=0;ii<iNumDevs;ii++) {
       
   262         if(waveInGetDevCaps(ii, &wic, sizeof(WAVEINCAPS))
       
   263 	    == MMSYSERR_NOERROR) {
       
   264 	    QString tmp;
       
   265             tmp = QString::fromWCharArray(wic.szPname);
       
   266 	    if(tmp.compare(QLatin1String(m_device)) == 0) {
       
   267 	        devId = ii;
       
   268 		break;
       
   269 	    }
       
   270 	}
       
   271     }
       
   272 
       
   273     if(waveInOpen(&hWaveIn, devId, &wfx,
       
   274                 (DWORD_PTR)&waveInProc,
       
   275                 (DWORD_PTR) this,
       
   276                 CALLBACK_FUNCTION) != MMSYSERR_NOERROR) {
       
   277         errorState = QAudio::OpenError;
       
   278         deviceState = QAudio::StoppedState;
       
   279         emit stateChanged(deviceState);
       
   280         qWarning("QAudioInput: failed to open audio device");
       
   281         return false;
       
   282     }
       
   283     waveBlocks = allocateBlocks(period_size, buffer_size/period_size);
       
   284 
       
   285     if(waveBlocks == 0) {
       
   286         errorState = QAudio::OpenError;
       
   287         deviceState = QAudio::StoppedState;
       
   288         emit stateChanged(deviceState);
       
   289         qWarning("QAudioInput: failed to allocate blocks. open failed");
       
   290         return false;
       
   291     }
       
   292 
       
   293     mutex.lock();
       
   294     waveFreeBlockCount = buffer_size/period_size;
       
   295     mutex.unlock();
       
   296 
       
   297     waveCurrentBlock = 0;
       
   298 
       
   299     for(int i=0; i<buffer_size/period_size; i++) {
       
   300         result = waveInAddBuffer(hWaveIn, &waveBlocks[i], sizeof(WAVEHDR));
       
   301         if(result != MMSYSERR_NOERROR) {
       
   302             qWarning("QAudioInput: failed to setup block %d,err=%d",i,result);
       
   303             errorState = QAudio::OpenError;
       
   304             deviceState = QAudio::StoppedState;
       
   305             emit stateChanged(deviceState);
       
   306             return false;
       
   307         }
       
   308     }
       
   309     result = waveInStart(hWaveIn);
       
   310     if(result) {
       
   311         qWarning("QAudioInput: failed to start audio input");
       
   312         errorState = QAudio::OpenError;
       
   313         deviceState = QAudio::StoppedState;
       
   314         emit stateChanged(deviceState);
       
   315         return false;
       
   316     }
       
   317     timeStampOpened.restart();
       
   318     elapsedTimeOffset = 0;
       
   319     totalTimeValue = 0;
       
   320     errorState  = QAudio::NoError;
       
   321     return true;
       
   322 }
       
   323 
       
   324 void QAudioInputPrivate::close()
       
   325 {
       
   326     if(deviceState == QAudio::StoppedState)
       
   327         return;
       
   328 
       
   329     deviceState = QAudio::StoppedState;
       
   330     waveInReset(hWaveIn);
       
   331     waveInClose(hWaveIn);
       
   332 
       
   333     int count = 0;
       
   334     while(!finished && count < 500) {
       
   335         count++;
       
   336         Sleep(10);
       
   337     }
       
   338 
       
   339     mutex.lock();
       
   340     for(int i=0; i<waveFreeBlockCount; i++)
       
   341         waveInUnprepareHeader(hWaveIn,&waveBlocks[i],sizeof(WAVEHDR));
       
   342     freeBlocks(waveBlocks);
       
   343     mutex.unlock();
       
   344 }
       
   345 
       
   346 int QAudioInputPrivate::bytesReady() const
       
   347 {
       
   348     if(period_size == 0 || buffer_size == 0)
       
   349         return 0;
       
   350 
       
   351     int buf = ((buffer_size/period_size)-waveFreeBlockCount)*period_size;
       
   352     if(buf < 0)
       
   353         buf = 0;
       
   354     return buf;
       
   355 }
       
   356 
       
   357 qint64 QAudioInputPrivate::read(char* data, qint64 len)
       
   358 {
       
   359     bool done = false;
       
   360 
       
   361     char*  p = data;
       
   362     qint64 l = 0;
       
   363     qint64 written = 0;
       
   364     while(!done) {
       
   365         // Read in some audio data
       
   366         if(waveBlocks[header].dwBytesRecorded > 0 && waveBlocks[header].dwFlags & WHDR_DONE) {
       
   367             if(pullMode) {
       
   368                 l = audioSource->write(waveBlocks[header].lpData,
       
   369                         waveBlocks[header].dwBytesRecorded);
       
   370 #ifdef DEBUG_AUDIO
       
   371                 qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l;
       
   372 #endif
       
   373                 if(l < 0) {
       
   374                     // error
       
   375                     qWarning("QAudioInput: IOError");
       
   376                     errorState = QAudio::IOError;
       
   377 
       
   378                 } else if(l == 0) {
       
   379                     // cant write to IODevice
       
   380                     qWarning("QAudioInput: IOError, can't write to QIODevice");
       
   381                     errorState = QAudio::IOError;
       
   382 
       
   383                 } else {
       
   384                     totalTimeValue += waveBlocks[header].dwBytesRecorded;
       
   385                     errorState = QAudio::NoError;
       
   386                     if (deviceState != QAudio::ActiveState) {
       
   387                         deviceState = QAudio::ActiveState;
       
   388                         emit stateChanged(deviceState);
       
   389                     }
       
   390 		    resuming = false;
       
   391                 }
       
   392             } else {
       
   393                 // push mode
       
   394                 memcpy(p,waveBlocks[header].lpData,waveBlocks[header].dwBytesRecorded);
       
   395                 l = waveBlocks[header].dwBytesRecorded;
       
   396 #ifdef DEBUG_AUDIO
       
   397                 qDebug()<<"IN: "<<waveBlocks[header].dwBytesRecorded<<", OUT: "<<l;
       
   398 #endif
       
   399                 totalTimeValue += waveBlocks[header].dwBytesRecorded;
       
   400                 errorState = QAudio::NoError;
       
   401                 if (deviceState != QAudio::ActiveState) {
       
   402                     deviceState = QAudio::ActiveState;
       
   403                     emit stateChanged(deviceState);
       
   404                 }
       
   405 		resuming = false;
       
   406             }
       
   407         } else {
       
   408             //no data, not ready yet, next time
       
   409             break;
       
   410         }
       
   411 
       
   412         waveInUnprepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
       
   413 
       
   414         mutex.lock();
       
   415         waveFreeBlockCount++;
       
   416         mutex.unlock();
       
   417 
       
   418         waveBlocks[header].dwBytesRecorded=0;
       
   419         waveBlocks[header].dwFlags = 0L;
       
   420         result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
       
   421         if(result != MMSYSERR_NOERROR) {
       
   422             result = waveInPrepareHeader(hWaveIn,&waveBlocks[header], sizeof(WAVEHDR));
       
   423             qWarning("QAudioInput: failed to prepare block %d,err=%d",header,result);
       
   424             errorState = QAudio::IOError;
       
   425 
       
   426             mutex.lock();
       
   427             waveFreeBlockCount--;
       
   428             mutex.unlock();
       
   429 
       
   430             return 0;
       
   431         }
       
   432         result = waveInAddBuffer(hWaveIn, &waveBlocks[header], sizeof(WAVEHDR));
       
   433         if(result != MMSYSERR_NOERROR) {
       
   434             qWarning("QAudioInput: failed to setup block %d,err=%d",header,result);
       
   435             errorState = QAudio::IOError;
       
   436 
       
   437             mutex.lock();
       
   438             waveFreeBlockCount--;
       
   439             mutex.unlock();
       
   440 
       
   441             return 0;
       
   442         }
       
   443         header++;
       
   444         if(header >= buffer_size/period_size)
       
   445             header = 0;
       
   446         p+=l;
       
   447 
       
   448         mutex.lock();
       
   449         if(!pullMode) {
       
   450 	    if(l+period_size > len && waveFreeBlockCount == buffer_size/period_size)
       
   451 	        done = true;
       
   452 	} else {
       
   453 	    if(waveFreeBlockCount == buffer_size/period_size)
       
   454 	        done = true;
       
   455 	}
       
   456         mutex.unlock();
       
   457 
       
   458 	written+=l;
       
   459     }
       
   460 #ifdef DEBUG_AUDIO
       
   461     qDebug()<<"read in len="<<written;
       
   462 #endif
       
   463     return written;
       
   464 }
       
   465 
       
   466 void QAudioInputPrivate::resume()
       
   467 {
       
   468     if(deviceState == QAudio::SuspendedState) {
       
   469         deviceState = QAudio::ActiveState;
       
   470         for(int i=0; i<buffer_size/period_size; i++) {
       
   471             result = waveInAddBuffer(hWaveIn, &waveBlocks[i], sizeof(WAVEHDR));
       
   472             if(result != MMSYSERR_NOERROR) {
       
   473                 qWarning("QAudioInput: failed to setup block %d,err=%d",i,result);
       
   474                 errorState = QAudio::OpenError;
       
   475                 deviceState = QAudio::StoppedState;
       
   476                 emit stateChanged(deviceState);
       
   477                 return;
       
   478             }
       
   479         }
       
   480 
       
   481         mutex.lock();
       
   482         waveFreeBlockCount = buffer_size/period_size;
       
   483         mutex.unlock();
       
   484 
       
   485         waveCurrentBlock = 0;
       
   486         header = 0;
       
   487 	resuming = true;
       
   488         waveInStart(hWaveIn);
       
   489         QTimer::singleShot(20,this,SLOT(feedback()));
       
   490         emit stateChanged(deviceState);
       
   491     }
       
   492 }
       
   493 
       
   494 void QAudioInputPrivate::setBufferSize(int value)
       
   495 {
       
   496     buffer_size = value;
       
   497 }
       
   498 
       
   499 int QAudioInputPrivate::bufferSize() const
       
   500 {
       
   501     return buffer_size;
       
   502 }
       
   503 
       
   504 int QAudioInputPrivate::periodSize() const
       
   505 {
       
   506     return period_size;
       
   507 }
       
   508 
       
   509 void QAudioInputPrivate::setNotifyInterval(int ms)
       
   510 {
       
   511     intervalTime = qMax(0, ms);
       
   512 }
       
   513 
       
   514 int QAudioInputPrivate::notifyInterval() const
       
   515 {
       
   516     return intervalTime;
       
   517 }
       
   518 
       
   519 qint64 QAudioInputPrivate::processedUSecs() const
       
   520 {
       
   521     if (deviceState == QAudio::StoppedState)
       
   522         return 0;
       
   523     qint64 result = qint64(1000000) * totalTimeValue /
       
   524         (settings.channels()*(settings.sampleSize()/8)) /
       
   525         settings.frequency();
       
   526 
       
   527     return result;
       
   528 }
       
   529 
       
   530 void QAudioInputPrivate::suspend()
       
   531 {
       
   532     if(deviceState == QAudio::ActiveState) {
       
   533         waveInReset(hWaveIn);
       
   534         deviceState = QAudio::SuspendedState;
       
   535         emit stateChanged(deviceState);
       
   536     }
       
   537 }
       
   538 
       
   539 void QAudioInputPrivate::feedback()
       
   540 {
       
   541 #ifdef DEBUG_AUDIO
       
   542     QTime now(QTime::currentTime());
       
   543     qDebug()<<now.second()<<"s "<<now.msec()<<"ms :feedback() INPUT "<<this;
       
   544 #endif
       
   545     if(!(deviceState==QAudio::StoppedState||deviceState==QAudio::SuspendedState))
       
   546         QMetaObject::invokeMethod(this, "deviceReady", Qt::QueuedConnection);
       
   547 }
       
   548 
       
   549 bool QAudioInputPrivate::deviceReady()
       
   550 {
       
   551     bytesAvailable = bytesReady();
       
   552 #ifdef DEBUG_AUDIO
       
   553     QTime now(QTime::currentTime());
       
   554     qDebug()<<now.second()<<"s "<<now.msec()<<"ms :deviceReady() INPUT";
       
   555 #endif
       
   556     if(deviceState != QAudio::ActiveState && deviceState != QAudio::IdleState)
       
   557         return true;
       
   558 
       
   559     if(pullMode) {
       
   560         // reads some audio data and writes it to QIODevice
       
   561         read(0,0);
       
   562     } else {
       
   563         // emits readyRead() so user will call read() on QIODevice to get some audio data
       
   564 	InputPrivate* a = qobject_cast<InputPrivate*>(audioSource);
       
   565 	a->trigger();
       
   566     }
       
   567 
       
   568     if(intervalTime && (timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
       
   569         emit notify();
       
   570         elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
       
   571         timeStamp.restart();
       
   572     }
       
   573     return true;
       
   574 }
       
   575 
       
   576 qint64 QAudioInputPrivate::elapsedUSecs() const
       
   577 {
       
   578     if (deviceState == QAudio::StoppedState)
       
   579         return 0;
       
   580 
       
   581     return timeStampOpened.elapsed()*1000;
       
   582 }
       
   583 
       
   584 void QAudioInputPrivate::reset()
       
   585 {
       
   586     close();
       
   587 }
       
   588 
       
   589 InputPrivate::InputPrivate(QAudioInputPrivate* audio)
       
   590 {
       
   591     audioDevice = qobject_cast<QAudioInputPrivate*>(audio);
       
   592 }
       
   593 
       
   594 InputPrivate::~InputPrivate() {}
       
   595 
       
   596 qint64 InputPrivate::readData( char* data, qint64 len)
       
   597 {
       
   598     // push mode, user read() called
       
   599     if(audioDevice->deviceState != QAudio::ActiveState &&
       
   600             audioDevice->deviceState != QAudio::IdleState)
       
   601         return 0;
       
   602     // Read in some audio data
       
   603     return audioDevice->read(data,len);
       
   604 }
       
   605 
       
   606 qint64 InputPrivate::writeData(const char* data, qint64 len)
       
   607 {
       
   608     Q_UNUSED(data)
       
   609     Q_UNUSED(len)
       
   610 
       
   611     emit readyRead();
       
   612     return 0;
       
   613 }
       
   614 
       
   615 void InputPrivate::trigger()
       
   616 {
       
   617     emit readyRead();
       
   618 }
       
   619 
       
   620 QT_END_NAMESPACE