📄 qsoundqss_qws.cpp
字号:
};int QWSSoundServerProvider::priorityExists = 0;class QWSSoundServerBucket : public QWSSoundServerProvider {public: QWSSoundServerBucket(int d, int wid, int sid) : QWSSoundServerProvider(wid, sid) { dev = d; wavedata_remaining = -1; mFinishedRead = false; mInsufficientSamples = false; } ~QWSSoundServerBucket() { //dev->close(); ::close(dev); } bool finished() const { //return !max; return mInsufficientSamples && mFinishedRead ; } int readySamples(int) { int size; char *dest = prepareBuffer(size); // may want to change this to something like // if (data == data1 && max2<<1 < sound_buffer_size // || // data == data2 && max1<<1 < sound_buffer_size) // so will keep filling off buffer while there is +50% space left if (size > 0 && dest != 0) { while ( wavedata_remaining < 0 ) { //max = 0; wavedata_remaining = -1; // Keep reading chunks... const int n = sizeof(chunk)-sizeof(chunk.data); int nr = ::read(dev, (void*)&chunk,n); if ( nr != n ) { // XXX check error? or don't we care? wavedata_remaining = 0; mFinishedRead = true; } else if ( qstrncmp(chunk.id,"data",4) == 0 ) { wavedata_remaining = chunk.size; //out = max = sound_buffer_size; } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) { char d[4]; if ( read(dev, d, 4) != 4 ) { // XXX check error? or don't we care? //qDebug("couldn't read riff"); mInsufficientSamples = true; mFinishedRead = true; return 0; } else if ( qstrncmp(d,"WAVE",4) != 0 ) { // skip if ( chunk.size > 1000000000 || lseek(dev,chunk.size-4, SEEK_CUR) == -1 ) { //qDebug("oversized wav chunk"); mFinishedRead = true; } } } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) { if ( ::read(dev,(char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) { // XXX check error? or don't we care? //qDebug("couldn't ready chunkdata"); mFinishedRead = true; }#define WAVE_FORMAT_PCM 1 else if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) { //qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag); mFinishedRead = true; } } else { // ignored chunk if ( chunk.size > 1000000000 || lseek(dev, chunk.size, SEEK_CUR) == -1) { //qDebug("chunk size too big"); mFinishedRead = true; } } } // this looks wrong. if (wavedata_remaining <= 0) { mFinishedRead = true; } } // may want to change this to something like // if (data == data1 && max2<<1 < sound_buffer_size // || // data == data2 && max1<<1 < sound_buffer_size) // so will keep filling off buffer while there is +50% space left if (wavedata_remaining) { if (size > 0 && dest != 0) { int read = ::read(dev, dest, qMin(size, wavedata_remaining)); // XXX check error? or don't we care? wavedata_remaining -= read; updateBuffer(read); if (read <= 0) // data unexpectidly ended mFinishedRead = true; } } int possible = devSamples(); if (possible == 0) mInsufficientSamples = true; return possible; }protected: QRiffChunk chunk; int wavedata_remaining; bool mFinishedRead; bool mInsufficientSamples;};class QWSSoundServerStream : public QWSSoundServerProvider {public: QWSSoundServerStream(int d,int c, int f, int b, int wid, int sid) : QWSSoundServerProvider(wid, sid) { chunkdata.channels = c; chunkdata.samplesPerSec = f; chunkdata.wBitsPerSample = b; dev = d; //fcntl( dev, F_SETFL, O_NONBLOCK ); lasttime = 0; } ~QWSSoundServerStream() { if (dev != -1) { ::close(dev); dev = -1; } } bool finished() const { return (dev == -1); } int readySamples(int) { int size; char *dest = prepareBuffer(size); if (size > 0 && dest != 0 && dev != -1) { int read = ::read(dev, dest, size); if (read < 0) { switch(errno) { case EAGAIN: case EINTR: // means read may yet succeed on the next attempt break; default: // unexpected error, fail. ::close(dev); dev = -1; } } else if (read == 0) { // 0 means writer has closed dev and/or // file is at end. ::close(dev); dev = -1; } else { updateBuffer(read); } } int possible = devSamples(); if (possible == 0) startSampleRunin(); return possible; }protected: time_t lasttime;};#ifndef QT_NO_QWS_SOUNDSERVERQWSSoundServerSocket::QWSSoundServerSocket(QObject *parent) : QWSServerSocket(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id), parent){ connect(this, SIGNAL(newConnection()), this, SLOT(newConnection()));}#ifdef QT3_SUPPORTQWSSoundServerSocket::QWSSoundServerSocket(QObject *parent, const char *name) : QWSServerSocket(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id), parent){ if (name) setObjectName(QString::fromAscii(name)); connect(this, SIGNAL(newConnection()), this, SLOT(newConnection()));}#endifvoid QWSSoundServerSocket::newConnection(){ while (QWS_SOCK_BASE *sock = nextPendingConnection()) { QWSSoundServerClient* client = new QWSSoundServerClient(sock,this); connect(client, SIGNAL(play(int,int,QString)), this, SIGNAL(playFile(int,int,QString))); connect(client, SIGNAL(play(int,int,QString,int,int)), this, SIGNAL(playFile(int,int,QString,int,int))); connect(client, SIGNAL(playRaw(int,int,QString,int,int,int,int)), this, SIGNAL(playRawFile(int,int,QString,int,int,int,int))); connect(client, SIGNAL(pause(int,int)), this, SIGNAL(pauseFile(int,int))); connect(client, SIGNAL(stop(int,int)), this, SIGNAL(stopFile(int,int))); connect(client, SIGNAL(playPriorityOnly(bool)), this, SIGNAL(playPriorityOnly(bool))); connect(client, SIGNAL(stopAll(int)), this, SIGNAL(stopAll(int))); connect(client, SIGNAL(resume(int,int)), this, SIGNAL(resumeFile(int,int))); connect(client, SIGNAL(setSilent(bool)), this, SIGNAL(setSilent(bool))); connect(client, SIGNAL(setMute(int,int,bool)), this, SIGNAL(setMute(int,int,bool))); connect(client, SIGNAL(setVolume(int,int,int,int)), this, SIGNAL(setVolume(int,int,int,int))); connect(this, SIGNAL(soundFileCompleted(int,int)), client, SLOT(sendSoundCompleted(int,int))); connect(this, SIGNAL(deviceReady(int,int)), client, SLOT(sendDeviceReady(int,int))); connect(this, SIGNAL(deviceError(int,int,int)), client, SLOT(sendDeviceError(int,int,int))); }}#endifclass QWSSoundServerPrivate : public QObject { Q_OBJECTpublic: QWSSoundServerPrivate(QObject* parent=0, const char* name=0) : QObject(parent) { timerId = 0; if (name) setObjectName(QString::fromAscii(name));#ifndef QT_NO_QWS_SOUNDSERVER server = new QWSSoundServerSocket(this); connect(server, SIGNAL(playFile(int,int,QString)), this, SLOT(playFile(int,int,QString))); connect(server, SIGNAL(playFile(int,int,QString,int,int)), this, SLOT(playFile(int,int,QString,int,int))); connect(server, SIGNAL(playRawFile(int,int,QString,int,int,int,int)), this, SLOT(playRawFile(int,int,QString,int,int,int,int))); connect(server, SIGNAL(pauseFile(int,int)), this, SLOT(pauseFile(int,int))); connect(server, SIGNAL(stopFile(int,int)), this, SLOT(stopFile(int,int))); connect(server, SIGNAL(stopAll(int)), this, SLOT(stopAll(int))); connect(server, SIGNAL(playPriorityOnly(bool)), this, SLOT(playPriorityOnly(bool))); connect(server, SIGNAL(resumeFile(int,int)), this, SLOT(resumeFile(int,int))); connect( server, SIGNAL(setSilent(bool)), this, SLOT(setSilent(bool))); connect(server, SIGNAL(setMute(int,int,bool)), this, SLOT(setMute(int,int,bool))); connect(server, SIGNAL(setVolume(int,int,int,int)), this, SLOT(setVolume(int,int,int,int))); connect(this, SIGNAL(soundFileCompleted(int,int)), server, SIGNAL(soundFileCompleted(int,int))); connect(this, SIGNAL(deviceReady(int,int)), server, SIGNAL(deviceReady(int,int))); connect(this, SIGNAL(deviceError(int,int,int)), server, SIGNAL(deviceError(int,int,int)));#endif silent = false; fd = -1; unwritten = 0; can_GETOSPACE = true; } ~QWSSoundServerPrivate() { qDeleteAll(active); qDeleteAll(inactive); }signals: void soundFileCompleted(int, int); void deviceReady(int, int); void deviceError(int, int, int);public slots: void playRawFile(int wid, int sid, const QString &filename, int freq, int channels, int bitspersample, int flags); void playFile(int wid, int sid, const QString& filename); void playFile(int wid, int sid, const QString& filename, int v, int flags); void checkPresetVolumes(int wid, int sid, QWSSoundServerProvider *p); void pauseFile(int wid, int sid); void resumeFile(int wid, int sid); void stopFile(int wid, int sid); void stopAll(int wid); void setVolume(int wid, int sid, int lv, int rv); void setMute(int wid, int sid, bool m); void playPriorityOnly(bool p); void sendCompletedSignals(); void feedDevice(int fd); void setSilent( bool enabled );protected: void timerEvent(QTimerEvent* event);private: int openFile(int wid, int sid, const QString& filename); bool openDevice(); void closeDevice() { if (fd >= 0) { ::close(fd); fd = -1; } } QList<QWSSoundServerProvider*> active; QList<QWSSoundServerProvider*> inactive; struct PresetVolume { int wid; int sid; int left; int right; bool mute; }; QList<PresetVolume> volumes; struct CompletedInfo { CompletedInfo( ) : groupId( 0 ), soundId( 0 ) { } CompletedInfo( int _groupId, int _soundId ) : groupId( _groupId ), soundId( _soundId ) { } int groupId; int soundId; }; QList<CompletedInfo> completed; bool silent; int fd; int unwritten; int timerId; char* cursor; short data[sound_buffer_size*2]; bool can_GETOSPACE;#ifndef QT_NO_QWS_SOUNDSERVER QWSSoundServerSocket *server;#endif};void QWSSoundServerPrivate::setSilent( bool enabled ){ // Close output device closeDevice(); if( !unwritten && !active.count() ) { sendCompletedSignals(); } // Stop processing audio killTimer( timerId ); silent = enabled; // If audio remaining, open output device and continue processing if( unwritten || active.count() ) { openDevice(); }}void QWSSoundServerPrivate::timerEvent(QTimerEvent* event){ // qDebug("QSS timer event"); if( event->timerId() == timerId ) { if (fd >= 0) feedDevice(fd); if (fd < 0) { killTimer(timerId); timerId = 0; } }}void QWSSoundServerPrivate::playRawFile(int wid, int sid, const QString &filename, int freq, int channels, int bitspersample, int flags){#ifdef QT_NO_QWS_SOUNDSERVER Q_UNUSED(flags);#endif int f = openFile(wid, sid, filename); if ( f ) { QWSSoundServerStream *b = new QWSSoundServerStream(f, channels, freq, bitspersample, wid, sid); // check preset volumes. checkPresetVolumes(wid, sid, b);#ifndef QT_NO_QWS_SOUNDSERVER b->setPriority(flags & QWSSoundClient::Priority == QWSSoundClient::Priority);#endif active.append(b); emit deviceReady(wid, sid); }}void QWSSoundServerPrivate::playFile(int wid, int sid, const QString& filename){ int f = openFile(wid, sid, filename); if ( f ) { QWSSoundServerProvider *b = new QWSSoundServerBucket(f, wid, sid); checkPresetVolumes(wid, sid, b); active.append( b ); emit deviceReady(wid, sid); }}void QWSSoundServerPrivate::playFile(int wid, int sid, const QString& filename, int v, int flags){#ifdef QT_NO_QWS_SOUNDSERVER Q_UNUSED(flags);#endif int f = openFile(wid, sid, filename); if ( f ) { QWSSoundServerProvider *b = new QWSSoundServerBucket(f, wid, sid); checkPresetVolumes(wid, sid, b); b->setVolume(v, v);#ifndef QT_NO_QWS_SOUNDSERVER b->setPriority(flags & QWSSoundClient::Priority == QWSSoundClient::Priority);#endif active.append(b); emit deviceReady(wid, sid); }}void QWSSoundServerPrivate::checkPresetVolumes(int wid, int sid, QWSSoundServerProvider *p){ QList<PresetVolume>::Iterator it = volumes.begin(); while (it != volumes.end()) { PresetVolume v = *it; if (v.wid == wid && v.sid == sid) { p->setVolume(v.left, v.right); p->setMute(v.mute); it = volumes.erase(it); return; } else { ++it; } }}void QWSSoundServerPrivate::pauseFile(int wid, int sid){ QWSSoundServerProvider *bucket; for (int i = 0; i < active.size(); ++i ) { bucket = active.at(i); if (bucket->equal(wid, sid)) { // found bucket.... active.removeAt(i); inactive.append(bucket); return; } }}void QWSSoundServerPrivate::resumeFile(int wid, int sid){ QWSSoundServerProvider *bucket; for (int i = 0; i < inactive.size(); ++i ) { bucket = inactive.at(i); if (bucket->equal(wid, sid)) { // found bucket.... inactive.removeAt(i); active.append(bucket); return; } }}void QWSSoundServerPrivate::stopFile(int wid, int sid){ QWSSoundServerProvider *bucket; for (int i = 0; i < active.size(); ++i ) { bucket = active.at(i); if (bucket->equal(wid, sid)) { active.removeAt(i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -