1 /**************************************************************************** |
1 /**************************************************************************** |
2 ** |
2 ** |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 ** All rights reserved. |
4 ** All rights reserved. |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 ** |
6 ** |
7 ** This file is part of the QtMultimedia module of the Qt Toolkit. |
7 ** This file is part of the QtMultimedia module of the Qt Toolkit. |
8 ** |
8 ** |
492 // Only write space worth |
493 // Only write space worth |
493 frames = snd_pcm_bytes_to_frames( handle, (int)space ); |
494 frames = snd_pcm_bytes_to_frames( handle, (int)space ); |
494 err = snd_pcm_writei( handle, data, frames ); |
495 err = snd_pcm_writei( handle, data, frames ); |
495 } |
496 } |
496 if(err > 0) { |
497 if(err > 0) { |
497 totalTimeValue += err*1000000/settings.frequency(); |
498 totalTimeValue += err; |
498 resuming = false; |
499 resuming = false; |
499 errorState = QAudio::NoError; |
500 errorState = QAudio::NoError; |
500 deviceState = QAudio::ActiveState; |
501 if (deviceState != QAudio::ActiveState) { |
|
502 deviceState = QAudio::ActiveState; |
|
503 emit stateChanged(deviceState); |
|
504 } |
501 return snd_pcm_frames_to_bytes( handle, err ); |
505 return snd_pcm_frames_to_bytes( handle, err ); |
502 } else |
506 } else |
503 err = xrun_recovery(err); |
507 err = xrun_recovery(err); |
504 |
508 |
505 if(err < 0) { |
509 if(err < 0) { |
560 xrun_recovery(err); |
564 xrun_recovery(err); |
561 |
565 |
562 bytesAvailable = (int)snd_pcm_frames_to_bytes(handle, buffer_frames); |
566 bytesAvailable = (int)snd_pcm_frames_to_bytes(handle, buffer_frames); |
563 } |
567 } |
564 resuming = true; |
568 resuming = true; |
565 if(pullMode) |
569 |
566 deviceState = QAudio::ActiveState; |
570 deviceState = QAudio::ActiveState; |
567 else |
|
568 deviceState = QAudio::IdleState; |
|
569 |
571 |
570 errorState = QAudio::NoError; |
572 errorState = QAudio::NoError; |
571 timer->start(period_time/1000); |
573 timer->start(period_time/1000); |
572 emit stateChanged(deviceState); |
574 emit stateChanged(deviceState); |
573 } |
575 } |
635 l = audioSource->read(audioBuffer,snd_pcm_frames_to_bytes(handle, input)); |
637 l = audioSource->read(audioBuffer,snd_pcm_frames_to_bytes(handle, input)); |
636 if(l > 0) { |
638 if(l > 0) { |
637 // Got some data to output |
639 // Got some data to output |
638 if(deviceState != QAudio::ActiveState) |
640 if(deviceState != QAudio::ActiveState) |
639 return true; |
641 return true; |
640 write(audioBuffer,l); |
642 qint64 bytesWritten = write(audioBuffer,l); |
|
643 if (bytesWritten != l) |
|
644 audioSource->seek(audioSource->pos()-(l-bytesWritten)); |
641 bytesAvailable = bytesFree(); |
645 bytesAvailable = bytesFree(); |
642 |
646 |
643 } else if(l == 0) { |
647 } else if(l == 0) { |
644 // Did not get any data to output |
648 // Did not get any data to output |
645 bytesAvailable = bytesFree(); |
649 bytesAvailable = bytesFree(); |
646 if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) { |
650 if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) { |
647 // Underrun |
651 // Underrun |
|
652 if (deviceState != QAudio::IdleState) { |
|
653 errorState = QAudio::UnderrunError; |
|
654 deviceState = QAudio::IdleState; |
|
655 emit stateChanged(deviceState); |
|
656 } |
|
657 } |
|
658 |
|
659 } else if(l < 0) { |
|
660 close(); |
|
661 errorState = QAudio::IOError; |
|
662 emit stateChanged(deviceState); |
|
663 } |
|
664 } else { |
|
665 bytesAvailable = bytesFree(); |
|
666 if(bytesAvailable > snd_pcm_frames_to_bytes(handle, buffer_frames-period_frames)) { |
|
667 // Underrun |
|
668 if (deviceState != QAudio::IdleState) { |
648 errorState = QAudio::UnderrunError; |
669 errorState = QAudio::UnderrunError; |
649 deviceState = QAudio::IdleState; |
670 deviceState = QAudio::IdleState; |
650 emit stateChanged(deviceState); |
671 emit stateChanged(deviceState); |
651 } |
672 } |
652 |
673 } |
653 } else if(l < 0) { |
674 } |
654 close(); |
|
655 errorState = QAudio::IOError; |
|
656 emit stateChanged(deviceState); |
|
657 } |
|
658 } else |
|
659 bytesAvailable = bytesFree(); |
|
660 |
675 |
661 if(deviceState != QAudio::ActiveState) |
676 if(deviceState != QAudio::ActiveState) |
662 return true; |
677 return true; |
663 |
678 |
664 if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { |
679 if((timeStamp.elapsed() + elapsedTimeOffset) > intervalTime) { |
669 return true; |
684 return true; |
670 } |
685 } |
671 |
686 |
672 qint64 QAudioOutputPrivate::elapsedUSecs() const |
687 qint64 QAudioOutputPrivate::elapsedUSecs() const |
673 { |
688 { |
674 if(!handle) |
|
675 return 0; |
|
676 |
|
677 if (deviceState == QAudio::StoppedState) |
689 if (deviceState == QAudio::StoppedState) |
678 return 0; |
690 return 0; |
679 |
691 |
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 |
|
700 return clockStamp.elapsed()*1000; |
692 return clockStamp.elapsed()*1000; |
701 #endif |
|
702 return 0; |
|
703 } |
693 } |
704 |
694 |
705 void QAudioOutputPrivate::reset() |
695 void QAudioOutputPrivate::reset() |
706 { |
696 { |
707 if(handle) |
697 if(handle) |