source: trunk/src/multimedia/audio/qaudioinput_alsa_p.cpp@ 616

Last change on this file since 616 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 20.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtMultimedia module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
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#include <QtCore/qcoreapplication.h>
54#include "qaudioinput_alsa_p.h"
55#include "qaudiodeviceinfo_alsa_p.h"
56
57QT_BEGIN_NAMESPACE
58
59//#define DEBUG_AUDIO 1
60
61static const int minimumIntervalTime = 50;
62
63QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFormat& audioFormat):
64 settings(audioFormat)
65{
66 bytesAvailable = 0;
67 handle = 0;
68 ahandler = 0;
69 access = SND_PCM_ACCESS_RW_INTERLEAVED;
70 pcmformat = SND_PCM_FORMAT_S16;
71 buffer_size = 0;
72 period_size = 0;
73 buffer_time = 100000;
74 period_time = 20000;
75 totalTimeValue = 0;
76 intervalTime = 1000;
77 audioBuffer = 0;
78 errorState = QAudio::NoError;
79 deviceState = QAudio::StoppedState;
80 audioSource = 0;
81 pullMode = true;
82 resuming = false;
83
84 m_device = device;
85
86 timer = new QTimer(this);
87 connect(timer,SIGNAL(timeout()),SLOT(userFeed()));
88}
89
90QAudioInputPrivate::~QAudioInputPrivate()
91{
92 close();
93 disconnect(timer, SIGNAL(timeout()));
94 QCoreApplication::processEvents();
95 delete timer;
96}
97
98QAudio::Error QAudioInputPrivate::error() const
99{
100 return errorState;
101}
102
103QAudio::State QAudioInputPrivate::state() const
104{
105 return deviceState;
106}
107
108
109QAudioFormat QAudioInputPrivate::format() const
110{
111 return settings;
112}
113
114int QAudioInputPrivate::xrun_recovery(int err)
115{
116 int count = 0;
117 bool reset = false;
118
119 if(err == -EPIPE) {
120 errorState = QAudio::UnderrunError;
121 err = snd_pcm_prepare(handle);
122 if(err < 0)
123 reset = true;
124
125 } else if((err == -ESTRPIPE)||(err == -EIO)) {
126 errorState = QAudio::IOError;
127 while((err = snd_pcm_resume(handle)) == -EAGAIN){
128 usleep(100);
129 count++;
130 if(count > 5) {
131 reset = true;
132 break;
133 }
134 }
135 if(err < 0) {
136 err = snd_pcm_prepare(handle);
137 if(err < 0)
138 reset = true;
139 }
140 }
141 if(reset) {
142 close();
143 open();
144 snd_pcm_prepare(handle);
145 return 0;
146 }
147 return err;
148}
149
150int QAudioInputPrivate::setFormat()
151{
152 snd_pcm_format_t format = SND_PCM_FORMAT_S16;
153
154 if(settings.sampleSize() == 8) {
155 format = SND_PCM_FORMAT_U8;
156 } else if(settings.sampleSize() == 16) {
157 if(settings.sampleType() == QAudioFormat::SignedInt) {
158 if(settings.byteOrder() == QAudioFormat::LittleEndian)
159 format = SND_PCM_FORMAT_S16_LE;
160 else
161 format = SND_PCM_FORMAT_S16_BE;
162 } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
163 if(settings.byteOrder() == QAudioFormat::LittleEndian)
164 format = SND_PCM_FORMAT_U16_LE;
165 else
166 format = SND_PCM_FORMAT_U16_BE;
167 }
168 } else if(settings.sampleSize() == 24) {
169 if(settings.sampleType() == QAudioFormat::SignedInt) {
170 if(settings.byteOrder() == QAudioFormat::LittleEndian)
171 format = SND_PCM_FORMAT_S24_LE;
172 else
173 format = SND_PCM_FORMAT_S24_BE;
174 } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
175 if(settings.byteOrder() == QAudioFormat::LittleEndian)
176 format = SND_PCM_FORMAT_U24_LE;
177 else
178 format = SND_PCM_FORMAT_U24_BE;
179 }
180 } else if(settings.sampleSize() == 32) {
181 if(settings.sampleType() == QAudioFormat::SignedInt) {
182 if(settings.byteOrder() == QAudioFormat::LittleEndian)
183 format = SND_PCM_FORMAT_S32_LE;
184 else
185 format = SND_PCM_FORMAT_S32_BE;
186 } else if(settings.sampleType() == QAudioFormat::UnSignedInt) {
187 if(settings.byteOrder() == QAudioFormat::LittleEndian)
188 format = SND_PCM_FORMAT_U32_LE;
189 else
190 format = SND_PCM_FORMAT_U32_BE;
191 } else if(settings.sampleType() == QAudioFormat::Float) {
192 if(settings.byteOrder() == QAudioFormat::LittleEndian)
193 format = SND_PCM_FORMAT_FLOAT_LE;
194 else
195 format = SND_PCM_FORMAT_FLOAT_BE;
196 }
197 } else if(settings.sampleSize() == 64) {
198 if(settings.byteOrder() == QAudioFormat::LittleEndian)
199 format = SND_PCM_FORMAT_FLOAT64_LE;
200 else
201 format = SND_PCM_FORMAT_FLOAT64_BE;
202 }
203
204 return snd_pcm_hw_params_set_format( handle, hwparams, format);
205}
206
207QIODevice* QAudioInputPrivate::start(QIODevice* device)
208{
209 if(deviceState != QAudio::StoppedState)
210 close();
211
212 if(!pullMode && audioSource) {
213 delete audioSource;
214 }
215
216 if(device) {
217 //set to pull mode
218 pullMode = true;
219 audioSource = device;
220 } else {
221 //set to push mode
222 pullMode = false;
223 audioSource = new InputPrivate(this);
224 audioSource->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
225 }
226
227 if( !open() )
228 return 0;
229
230 emit stateChanged(deviceState);
231
232 return audioSource;
233}
234
235void QAudioInputPrivate::stop()
236{
237 if(deviceState == QAudio::StoppedState)
238 return;
239
240 deviceState = QAudio::StoppedState;
241
242 close();
243 emit stateChanged(deviceState);
244}
245
246bool QAudioInputPrivate::open()
247{
248#ifdef DEBUG_AUDIO
249 QTime now(QTime::currentTime());
250 qDebug()<<now.second()<<"s "<<now.msec()<<"ms :open()";
251#endif
252 clockStamp.restart();
253 timeStamp.restart();
254 elapsedTimeOffset = 0;
255
256 int dir;
257 int err=-1;
258 int count=0;
259 unsigned int freakuency=settings.frequency();
260
261 QString dev = QString(QLatin1String(m_device.constData()));
262 QList<QByteArray> devices = QAudioDeviceInfoInternal::availableDevices(QAudio::AudioInput);
263 if(dev.compare(QLatin1String("default")) == 0) {
264#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
265 dev = QLatin1String(devices.first());
266#else
267 dev = QLatin1String("hw:0,0");
268#endif
269 } else {
270#if(SND_LIB_MAJOR == 1 && SND_LIB_MINOR == 0 && SND_LIB_SUBMINOR >= 14)
271 dev = QLatin1String(m_device);
272#else
273 int idx = 0;
274 char *name;
275
276 QString shortName = QLatin1String(m_device.mid(m_device.indexOf('=',0)+1).constData());
277
278 while(snd_card_get_name(idx,&name) == 0) {
279 if(qstrncmp(shortName.toLocal8Bit().constData(),name,shortName.length()) == 0)
280 break;
281 idx++;
282 }
283 dev = QString(QLatin1String("hw:%1,0")).arg(idx);
284#endif
285 }
286
287 // Step 1: try and open the device
288 while((count < 5) && (err < 0)) {
289 err=snd_pcm_open(&handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_CAPTURE,0);
290 if(err < 0)
291 count++;
292 }
293 if (( err < 0)||(handle == 0)) {
294 errorState = QAudio::OpenError;
295 deviceState = QAudio::StoppedState;
296 emit stateChanged(deviceState);
297 return false;
298 }
299 snd_pcm_nonblock( handle, 0 );
300
301 // Step 2: Set the desired HW parameters.
302 snd_pcm_hw_params_alloca( &hwparams );
303
304 bool fatal = false;
305 QString errMessage;
306 unsigned int chunks = 8;
307
308 err = snd_pcm_hw_params_any( handle, hwparams );
309 if ( err < 0 ) {
310 fatal = true;
311 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_any: err = %1").arg(err);
312 }
313 if ( !fatal ) {
314 err = snd_pcm_hw_params_set_rate_resample( handle, hwparams, 1 );
315 if ( err < 0 ) {
316 fatal = true;
317 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_resample: err = %1").arg(err);
318 }
319 }
320 if ( !fatal ) {
321 err = snd_pcm_hw_params_set_access( handle, hwparams, access );
322 if ( err < 0 ) {
323 fatal = true;
324 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_access: err = %1").arg(err);
325 }
326 }
327 if ( !fatal ) {
328 err = setFormat();
329 if ( err < 0 ) {
330 fatal = true;
331 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_format: err = %1").arg(err);
332 }
333 }
334 if ( !fatal ) {
335 err = snd_pcm_hw_params_set_channels( handle, hwparams, (unsigned int)settings.channels() );
336 if ( err < 0 ) {
337 fatal = true;
338 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_channels: err = %1").arg(err);
339 }
340 }
341 if ( !fatal ) {
342 err = snd_pcm_hw_params_set_rate_near( handle, hwparams, &freakuency, 0 );
343 if ( err < 0 ) {
344 fatal = true;
345 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_rate_near: err = %1").arg(err);
346 }
347 }
348 if ( !fatal ) {
349 err = snd_pcm_hw_params_set_buffer_time_near(handle, hwparams, &buffer_time, &dir);
350 if ( err < 0 ) {
351 fatal = true;
352 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_buffer_time_near: err = %1").arg(err);
353 }
354 }
355 if ( !fatal ) {
356 err = snd_pcm_hw_params_set_period_time_near(handle, hwparams, &period_time, &dir);
357 if ( err < 0 ) {
358 fatal = true;
359 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_period_time_near: err = %1").arg(err);
360 }
361 }
362 if ( !fatal ) {
363 err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &chunks, &dir);
364 if ( err < 0 ) {
365 fatal = true;
366 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params_set_periods_near: err = %1").arg(err);
367 }
368 }
369 if ( !fatal ) {
370 err = snd_pcm_hw_params(handle, hwparams);
371 if ( err < 0 ) {
372 fatal = true;
373 errMessage = QString::fromLatin1("QAudioInput: snd_pcm_hw_params: err = %1").arg(err);
374 }
375 }
376 if( err < 0) {
377 qWarning()<<errMessage;
378 errorState = QAudio::OpenError;
379 deviceState = QAudio::StoppedState;
380 emit stateChanged(deviceState);
381 return false;
382 }
383 snd_pcm_hw_params_get_buffer_size(hwparams,&buffer_frames);
384 buffer_size = snd_pcm_frames_to_bytes(handle,buffer_frames);
385 snd_pcm_hw_params_get_period_size(hwparams,&period_frames, &dir);
386 period_size = snd_pcm_frames_to_bytes(handle,period_frames);
387 snd_pcm_hw_params_get_buffer_time(hwparams,&buffer_time, &dir);
388 snd_pcm_hw_params_get_period_time(hwparams,&period_time, &dir);
389
390 // Step 3: Set the desired SW parameters.
391 snd_pcm_sw_params_t *swparams;
392 snd_pcm_sw_params_alloca(&swparams);
393 snd_pcm_sw_params_current(handle, swparams);
394 snd_pcm_sw_params_set_start_threshold(handle,swparams,period_frames);
395 snd_pcm_sw_params_set_stop_threshold(handle,swparams,buffer_frames);
396 snd_pcm_sw_params_set_avail_min(handle, swparams,period_frames);
397 snd_pcm_sw_params(handle, swparams);
398
399 // Step 4: Prepare audio
400 if(audioBuffer == 0)
401 audioBuffer = new char[buffer_size];
402 snd_pcm_prepare( handle );
403 snd_pcm_start(handle);
404
405 // Step 5: Setup timer
406 bytesAvailable = bytesReady();
407
408 if(pullMode)
409 connect(audioSource,SIGNAL(readyRead()),this,SLOT(userFeed()));
410
411 // Step 6: Start audio processing
412 chunks = buffer_size/period_size;
413 timer->start(period_time*chunks/2000);
414
415 errorState = QAudio::NoError;
416 deviceState = QAudio::ActiveState;
417
418 totalTimeValue = 0;
419
420 return true;
421}
422
423void QAudioInputPrivate::close()
424{
425 deviceState = QAudio::StoppedState;
426 timer->stop();
427
428 if ( handle ) {
429 snd_pcm_drop( handle );
430 snd_pcm_close( handle );
431 handle = 0;
432 delete [] audioBuffer;
433 audioBuffer=0;
434 }
435}
436
437int QAudioInputPrivate::bytesReady() const
438{
439 if(resuming)
440 return period_size;
441
442 if(deviceState != QAudio::ActiveState)
443 return 0;
444 int frames = snd_pcm_avail_update(handle);
445 if((int)frames > (int)buffer_frames)
446 frames = buffer_frames;
447
448 return snd_pcm_frames_to_bytes(handle, frames);
449}
450
451qint64 QAudioInputPrivate::read(char* data, qint64 len)
452{
453 Q_UNUSED(data)
454 Q_UNUSED(len)
455 // Read in some audio data and write it to QIODevice, pull mode
456 if ( !handle )
457 return 0;
458
459 bytesAvailable = bytesReady();
460
461 int count=0, err = 0;
462 while(count < 5) {
463 int chunks = bytesAvailable/period_size;
464 int frames = chunks*period_frames;
465 if(frames > (int)buffer_frames)
466 frames = buffer_frames;
467 int readFrames = snd_pcm_readi(handle, audioBuffer, frames);
468 if (readFrames >= 0) {
469 err = snd_pcm_frames_to_bytes(handle, readFrames);
470#ifdef DEBUG_AUDIO
471 qDebug()<<QString::fromLatin1("PULL: read in bytes = %1 (frames=%2)").arg(err).arg(readFrames).toLatin1().constData();
472#endif
473 break;
474 } else if((readFrames == -EAGAIN) || (readFrames == -EINTR)) {
475 errorState = QAudio::IOError;
476 err = 0;
477 break;
478 } else {
479 if(readFrames == -EPIPE) {
480 errorState = QAudio::UnderrunError;
481 err = snd_pcm_prepare(handle);
482 } else if(readFrames == -ESTRPIPE) {
483 err = snd_pcm_prepare(handle);
484 }
485 if(err != 0) break;
486 }
487 count++;
488 }
489 if(err > 0) {
490 // got some send it onward
491#ifdef DEBUG_AUDIO
492 qDebug()<<"PULL: frames to write to QIODevice = "<<
493 snd_pcm_bytes_to_frames( handle, (int)err )<<" ("<<err<<") bytes";
494#endif
495 if(deviceState != QAudio::ActiveState)
496 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;
507 } else {
508 totalTimeValue += snd_pcm_bytes_to_frames(handle, err)*1000000/settings.frequency();
509 resuming = false;
510 errorState = QAudio::NoError;
511 deviceState = QAudio::ActiveState;
512 }
513 return l;
514 }
515 return 0;
516}
517
518void QAudioInputPrivate::resume()
519{
520 if(deviceState == QAudio::SuspendedState) {
521 int err = 0;
522
523 if(handle) {
524 err = snd_pcm_prepare( handle );
525 if(err < 0)
526 xrun_recovery(err);
527
528 err = snd_pcm_start(handle);
529 if(err < 0)
530 xrun_recovery(err);
531
532 bytesAvailable = buffer_size;
533 }
534 resuming = true;
535 deviceState = QAudio::ActiveState;
536 int chunks = buffer_size/period_size;
537 timer->start(buffer_time*chunks/2000);
538 emit stateChanged(deviceState);
539 }
540}
541
542void QAudioInputPrivate::setBufferSize(int value)
543{
544 buffer_size = value;
545}
546
547int QAudioInputPrivate::bufferSize() const
548{
549 return buffer_size;
550}
551
552int QAudioInputPrivate::periodSize() const
553{
554 return period_size;
555}
556
557void QAudioInputPrivate::setNotifyInterval(int ms)
558{
559 if(ms >= minimumIntervalTime)
560 intervalTime = ms;
561 else
562 intervalTime = minimumIntervalTime;
563}
564
565int QAudioInputPrivate::notifyInterval() const
566{
567 return intervalTime;
568}
569
570qint64 QAudioInputPrivate::processedUSecs() const
571{
572 return totalTimeValue;
573}
574
575void QAudioInputPrivate::suspend()
576{
577 if(deviceState == QAudio::ActiveState||resuming) {
578 timer->stop();
579 deviceState = QAudio::SuspendedState;
580 emit stateChanged(deviceState);
581 }
582}
583
584void QAudioInputPrivate::userFeed()
585{
586 if(deviceState == QAudio::StoppedState || deviceState == QAudio::SuspendedState)
587 return;
588#ifdef DEBUG_AUDIO
589 QTime now(QTime::currentTime());
590 qDebug()<<now.second()<<"s "<<now.msec()<<"ms :userFeed() IN";
591#endif
592 deviceReady();
593}
594
595bool QAudioInputPrivate::deviceReady()
596{
597 if(pullMode) {
598 // reads some audio data and writes it to QIODevice
599 read(0,0);
600 } else {
601 // emits readyRead() so user will call read() on QIODevice to get some audio data
602 InputPrivate* a = qobject_cast<InputPrivate*>(audioSource);
603 a->trigger();
604 }
605 bytesAvailable = bytesReady();
606
607 if(deviceState != QAudio::ActiveState)
608 return true;
609
610 if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) {
611 emit notify();
612 elapsedTimeOffset = timeStamp.elapsed() + elapsedTimeOffset - intervalTime;
613 timeStamp.restart();
614 }
615 return true;
616}
617
618qint64 QAudioInputPrivate::elapsedUSecs() const
619{
620 if(!handle)
621 return 0;
622
623 if (deviceState == QAudio::StoppedState)
624 return 0;
625
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
646 return clockStamp.elapsed()*1000;
647#endif
648}
649
650void QAudioInputPrivate::reset()
651{
652 if(handle)
653 snd_pcm_reset(handle);
654}
655
656void QAudioInputPrivate::drain()
657{
658 if(handle)
659 snd_pcm_drain(handle);
660}
661
662InputPrivate::InputPrivate(QAudioInputPrivate* audio)
663{
664 audioDevice = qobject_cast<QAudioInputPrivate*>(audio);
665}
666
667InputPrivate::~InputPrivate()
668{
669}
670
671qint64 InputPrivate::readData( char* data, qint64 len)
672{
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;
710}
711
712qint64 InputPrivate::writeData(const char* data, qint64 len)
713{
714 Q_UNUSED(data)
715 Q_UNUSED(len)
716 return 0;
717}
718
719void InputPrivate::trigger()
720{
721 emit readyRead();
722}
723
724QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.