00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qapplication.h>
00022 #include <qmessagebox.h>
00023
00024 #include "playthread.hh"
00025
00026 #include <iostream>
00027
00028 void PlayThread::run()
00029 {
00030 int res;
00031 char *offs = data;
00032
00033 stop_now = false;
00034
00035 if(format.access == SND_PCM_ACCESS_RW_INTERLEAVED)
00036 while(!stop_now && datasize > 0) {
00037 int frames = snd_pcm_bytes_to_frames(pcm_handle, datasize);
00038 res = snd_pcm_writei(pcm_handle, offs, frames);
00039 if(res > 0) {
00040 int written = snd_pcm_frames_to_bytes(pcm_handle, res);
00041 datasize -= written;
00042 offs += written;
00043 }
00044 else if(res < 0) {
00045 QMessageBox::critical(parent, tr("Cannot write to PCM device"),
00046 tr("Cannot write to the PCM device!"),
00047 QMessageBox::Cancel, QMessageBox::NoButton);
00048 break;
00049 }
00050
00051 #ifdef WHITE_LINE
00052 long delay;
00053 if(snd_pcm_delay(pcm_handle, &delay) < 0) {
00054 QMessageBox::critical(parent, tr("Cannot get PCM delay"),
00055 tr("Cannot get the delay of the PCM stream!"),
00056 QMessageBox::Cancel, QMessageBox::NoButton);
00057 break;
00058 }
00059 if(pos_lock->tryLock()) {
00060 *play_position = (double)(offs - data - delay * multiply) /
00061 (double)datasize;
00062 pos_lock->unlock();
00063 }
00064 #endif // WHITE_LINE
00065 }
00066 else {
00067
00068 }
00069
00070 if(stop_now) {
00071 if(snd_pcm_drop(pcm_handle) < 0) {
00072 QMessageBox::critical(parent, tr("Cannot stop PCM playback"),
00073 tr("Cannot stop the PCM playback!"),
00074 QMessageBox::Cancel, QMessageBox::NoButton);
00075 }
00076 } else {
00077
00078 #ifdef WHITE_LINE
00079 long delay = 1;
00080 while(delay > 0) {
00081 if(snd_pcm_delay(pcm_handle, &delay) < 0) {
00082 QMessageBox::critical(parent, tr("Cannot get PCM delay"),
00083 tr("Cannot get the delay of the PCM stream!"),
00084 QMessageBox::Cancel, QMessageBox::NoButton);
00085 break;
00086 }
00087 if(pos_lock->tryLock()) {
00088 *play_position = (double)(offs - data - delay * multiply) /
00089 (double)datasize;
00090 pos_lock->unlock();
00091 }
00092 }
00093 #endif // WHITE_LINE
00094
00095 if(snd_pcm_drain(pcm_handle) < 0) {
00096 QMessageBox::critical(parent, tr("Cannot stop PCM playback"),
00097 tr("Cannot stop the PCM playback!"),
00098 QMessageBox::Cancel, QMessageBox::NoButton);
00099 }
00100 }
00101
00102 if(snd_pcm_close(pcm_handle) < 0) {
00103 QMessageBox::critical(parent, tr("Cannot close PCM device"),
00104 tr("Cannot close the PCM device!"),
00105 QMessageBox::Cancel, QMessageBox::NoButton);
00106 }
00107
00108 QApplication::postEvent(parent, new QCustomEvent(Finished));
00109 }
00110
00111 void PlayThread::initThread(QWidget *obj, snd_pcm_t *handle,
00112 QMutex *mutex, double *playpos)
00113 {
00114 parent = obj;
00115 pcm_handle = handle;
00116 pos_lock = mutex;
00117 play_position = playpos;
00118 }
00119
00120 void PlayThread::loadData(char *ptr, size_t size, WaveFormat f)
00121 {
00122 data = ptr;
00123 datasize = size;
00124 format = f;
00125 }
00126
00127 void PlayThread::customEvent(QCustomEvent *e)
00128 {
00129 if(e->type() == (QEvent::Type)Stop)
00130 stop_now = true;
00131 }