📄 qsoundqss_qws.cpp
字号:
delete bucket; return; } } for (int i = 0; i < inactive.size(); ++i ) { bucket = inactive.at(i); if (bucket->equal(wid, sid)) { inactive.removeAt(i); delete bucket; return; } }}void QWSSoundServerPrivate::stopAll(int wid){ QWSSoundServerProvider *bucket; QList<QWSSoundServerProvider*>::Iterator it = active.begin(); while (it != active.end()) { bucket = *it; if (bucket->groupId() == wid) { it = active.erase(it); delete bucket; } else { ++it; } } it = inactive.begin(); while (it != inactive.end()) { bucket = *it; if (bucket->groupId() == wid) { it = inactive.erase(it); delete bucket; } else { ++it; } }}void QWSSoundServerPrivate::setVolume(int wid, int sid, int lv, int rv){ QWSSoundServerProvider *bucket; for( int i = 0; i < active.size(); ++i ) { bucket = active.at(i); if (bucket->equal(wid, sid)) { bucket->setVolume(lv,rv); return; } } // If gotten here, then it means wid/sid wasn't set up yet. // first find and remove current preset volumes, then add this one. QList<PresetVolume>::Iterator it = volumes.begin(); while (it != volumes.end()) { PresetVolume v = *it; if (v.wid == wid && v.sid == sid) it = volumes.erase(it); else ++it; } // and then add this volume PresetVolume nv; nv.wid = wid; nv.sid = sid; nv.left = lv; nv.right = rv; nv.mute = false; volumes.append(nv);}void QWSSoundServerPrivate::setMute(int wid, int sid, bool m){ QWSSoundServerProvider *bucket; for( int i = 0; i < active.size(); ++i ) { bucket = active.at(i); if (bucket->equal(wid, sid)) { bucket->setMute(m); return; } } // if gotten here then setting is being applied before item // is created. QList<PresetVolume>::Iterator it = volumes.begin(); while (it != volumes.end()) { PresetVolume v = *it; if (v.wid == wid && v.sid == sid) { (*it).mute = m; return; } } if (m) { PresetVolume nv; nv.wid = wid; nv.sid = sid; nv.left = maxVolume>>1; nv.right = maxVolume>>1; nv.mute = true; volumes.append(nv); }}void QWSSoundServerPrivate::playPriorityOnly(bool p){ QWSSoundServerProvider::setPlayPriorityOnly(p);}void QWSSoundServerPrivate::sendCompletedSignals(){ while( !completed.isEmpty() ) { emit soundFileCompleted( (*completed.begin()).groupId, (*completed.begin()).soundId ); completed.erase( completed.begin() ); }}int QWSSoundServerPrivate::openFile(int wid, int sid, const QString& filename){ stopFile(wid, sid); // close and re-open. int f = ::open(QFile::encodeName(filename), O_RDONLY|O_NONBLOCK); if (f == -1) { // XXX check ferror, check reason. qDebug("Failed opening \"%s\"",filename.toLatin1().data());#ifndef QT_NO_QWS_SOUNDSERVER emit deviceError(wid, sid, (int)QWSSoundClient::ErrOpeningFile );#endif } else if ( openDevice() ) { return f; }#ifndef QT_NO_QWS_SOUNDSERVER emit deviceError(wid, sid, (int)QWSSoundClient::ErrOpeningAudioDevice );#endif return 0;}bool QWSSoundServerPrivate::openDevice(){ if (fd < 0) { if( silent ) { fd = ::open( "/dev/null", O_WRONLY ); // Emulate write to audio device int delay = 1000*(sound_buffer_size>>(sound_stereo+sound_16bit))/sound_speed/2; timerId = startTimer(delay); return true; } // // Don't block open right away. // bool openOkay = false; if ((fd = ::open("/dev/dsp", O_WRONLY|O_NONBLOCK)) != -1) { int flags = fcntl(fd, F_GETFL); flags &= ~O_NONBLOCK; openOkay = (fcntl(fd, F_SETFL, flags) == 0); } if (!openOkay) { qDebug("Failed opening audio device"); return false; } // Setup soundcard at 16 bit mono int v; //v=0x00010000+sound_fragment_size; // um the media player did this instead. v=0x10000 * 4 + sound_fragment_size; if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &v)) qWarning("Could not set fragments to %08x",v);#ifdef QT_QWS_SOUND_16BIT v=AFMT_S16_LE; if (ioctl(fd, SNDCTL_DSP_SETFMT, &v)) qWarning("Could not set format %d",v); if (AFMT_S16_LE != v) qDebug("Want format %d got %d", AFMT_S16_LE, v);#else v=AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &v)) qWarning("Could not set format %d",v); if (AFMT_U8 != v) qDebug("Want format %d got %d", AFMT_U8, v);#endif v=sound_stereo; if (ioctl(fd, SNDCTL_DSP_STEREO, &v)) qWarning("Could not set stereo %d",v); if (sound_stereo != v) qDebug("Want stereo %d got %d", sound_stereo, v);#ifdef QT_QWS_SOUND_STEREO sound_stereo=v;#endif v=sound_speed; if (ioctl(fd, SNDCTL_DSP_SPEED, &sound_speed)) qWarning("Could not set speed %d",v); if (v != sound_speed) qDebug("Want speed %d got %d", v, sound_speed); int delay = 1000*(sound_buffer_size>>(sound_stereo+sound_16bit)) /sound_speed/2; // qDebug("QSS delay: %d", delay); timerId = startTimer(delay); // // Check system volume // int mixerHandle = ::open( "/dev/mixer", O_RDWR|O_NONBLOCK ); if ( mixerHandle >= 0 ) { int volume; ioctl( mixerHandle, MIXER_READ(0), &volume ); close( mixerHandle ); if ( volume < 1<<(sound_stereo+sound_16bit) ) qDebug("Want sound at %d got %d", 1<<(sound_stereo+sound_16bit), volume); } else qDebug( "get volume of audio device failed" ); } return true;}void QWSSoundServerPrivate::feedDevice(int fd){ if ( !unwritten && active.size() == 0 ) { closeDevice(); sendCompletedSignals(); return; } else { sendCompletedSignals(); } QWSSoundServerProvider* bucket; // find out how much audio is possible int available = sound_buffer_size; QList<QWSSoundServerProvider*> running; for (int i = 0; i < active.size(); ++i) { bucket = active.at(i); int ready = bucket->readySamples(available); if (ready > 0) { available = qMin(available, ready); running.append(bucket); } } audio_buf_info info; if (can_GETOSPACE && ioctl(fd,SNDCTL_DSP_GETOSPACE,&info)) { can_GETOSPACE = false; fcntl(fd, F_SETFL, O_NONBLOCK); } if (!can_GETOSPACE) info.fragments = 4; // #### configurable? if (info.fragments > 0) { if (!unwritten) { int left[sound_buffer_size]; memset(left,0,available*sizeof(int)); int right[sound_buffer_size]; if ( sound_stereo ) memset(right,0,available*sizeof(int)); if (running.size() > 0) { // should do volume mod here in regards to each bucket to avoid flattened/bad peaks. for (int i = 0; i < running.size(); ++i ) { bucket = running.at(i); int unused = bucket->add(left,right,available); if (unused > 0) { // this error is quite serious, as // it will really screw up mixing. qDebug("provider lied about samples ready"); } } if ( sound_16bit ) { short *d = (short*)data; for (int i=0; i<available; i++) { *d++ = (short)qMax(qMin(left[i],32767),-32768); if ( sound_stereo ) *d++ = (short)qMax(qMin(right[i],32767),-32768); } } else { signed char *d = (signed char *)data; for (int i=0; i<available; i++) { *d++ = (signed char)qMax(qMin(left[i]/256,127),-128)+128; if ( sound_stereo ) *d++ = (signed char)qMax(qMin(right[i]/256,127),-128)+128; } } unwritten = available*(sound_16bit+1)*(sound_stereo+1); cursor = (char*)data; } } // sound open, but nothing written. Should clear the buffer. int w; if (unwritten) { w = ::write(fd,cursor,unwritten); if ( w < 0 ) if ( !can_GETOSPACE ) w = 0; else return; cursor += w; unwritten -= w; } else { // write some zeros to clear the buffer? if (!zeroMem) zeroMem = (char *)calloc(sound_buffer_size, sizeof(char)); w = ::write(fd, zeroMem, sound_buffer_size); if (w < 0) w = 0; } } QList<QWSSoundServerProvider*>::Iterator it = active.begin(); while (it != active.end()) { bucket = *it; if (bucket->finished()) { completed.append(CompletedInfo(bucket->groupId(), bucket->soundId())); it = active.erase(it); delete bucket; } else { ++it; } }}QWSSoundServer::QWSSoundServer(QObject* parent) : QObject(parent){ d = new QWSSoundServerPrivate(this); connect( d, SIGNAL(soundFileCompleted(int,int)), this, SLOT(translateSoundCompleted(int,int)) );}void QWSSoundServer::playFile( int sid, const QString& filename ){ //wid == 0, as it is the server initiating rather than a client // if wid was passable, would accidently collide with server // sockect's wids. d->playFile(0, sid, filename);}void QWSSoundServer::pauseFile( int sid ){ d->pauseFile(0, sid);}void QWSSoundServer::stopFile( int sid ){ d->stopFile(0, sid);}void QWSSoundServer::resumeFile( int sid ){ d->resumeFile(0, sid);}QWSSoundServer::~QWSSoundServer(){ d->stopAll(0);}void QWSSoundServer::translateSoundCompleted( int, int sid ){ emit soundCompleted( sid );}#ifndef QT_NO_QWS_SOUNDSERVERQWSSoundClient::QWSSoundClient(QObject* parent) : QWSSocket(parent){ connectToLocalFile(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id)); QObject::connect(this,SIGNAL(readyRead()), this,SLOT(tryReadCommand())); if( state() == QWS_SOCK_BASE::ConnectedState ) QTimer::singleShot(1, this, SIGNAL(connected())); else QTimer::singleShot(1, this, SLOT(emitConnectionRefused()));}QWSSoundClient::~QWSSoundClient( ){ flush();}void QWSSoundClient::reconnect(){ connectToLocalFile(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id)); if( state() == QWS_SOCK_BASE::ConnectedState ) emit connected(); else emit error( QTcpSocket::ConnectionRefusedError );}void QWSSoundClient::sendServerMessage(QString msg){#ifndef QT_NO_TEXTCODEC QByteArray u = msg.toUtf8();#else QByteArray u = msg.toLatin1();#endif write(u.data(), u.length()); flush();}void QWSSoundClient::play( int id, const QString& filename ){ QFileInfo fi(filename); sendServerMessage(QLatin1String("PLAY ") + QString::number(id) + QLatin1Char(' ') + fi.absoluteFilePath() + QLatin1Char('\n'));}void QWSSoundClient::play( int id, const QString& filename, int volume, int flags){ QFileInfo fi(filename); sendServerMessage(QLatin1String("PLAYEXTEND ") + QString::number(id) + QLatin1Char(' ') + QString::number(volume) + QLatin1Char(' ') + QString::number(flags) + QLatin1Char(' ') + fi.absoluteFilePath() + QLatin1Char('\n'));}void QWSSoundClient::pause( int id ){ sendServerMessage(QLatin1String("PAUSE ") + QString::number(id) + QLatin1Char('\n'));}void QWSSoundClient::stop( int id ){ sendServerMessage(QLatin1String("STOP ") + QString::number(id) + QLatin1Char('\n'));}void QWSSoundClient::resume( int id ){ sendServerMessage(QLatin1String("RESUME ") + QString::number(id) + QLatin1Char('\n'));}void QWSSoundClient::playRaw( int id, const QString& filename, int freq, int chs, int bitspersample, int flags){ QFileInfo fi(filename); sendServerMessage(QLatin1String("PLAYRAW ") + QString::number(id) + QLatin1Char(' ') + QString::number(chs) + QLatin1Char(' ') + QString::number(freq) + QLatin1Char(' ') + QString::number(bitspersample) + QLatin1Char(' ') + QString::number(flags) + QLatin1Char(' ') + fi.absoluteFilePath() + QLatin1Char('\n'));}void QWSSoundClient::setMute( int id, bool m ){ sendServerMessage(QLatin1String(m ? "MUTE " : "UNMUTE ") + QString::number(id) + QLatin1Char('\n'));}void QWSSoundClient::setVolume( int id, int leftVol, int rightVol ){ sendServerMessage(QLatin1String("SETVOLUME ") + QString::number(id) + QLatin1Char(' ') + QString::number(leftVol) + QLatin1Char(' ') + QString::number(rightVol) + QLatin1Char('\n'));}void QWSSoundClient::playPriorityOnly( bool pri ){ sendServerMessage(QLatin1String("PRIORITYONLY ") + QString::number(pri ? 1 : 0) + QLatin1Char('\n'));}void QWSSoundClient::setSilent( bool enable ){ sendServerMessage(QLatin1String("SILENT ") + QString::number( enable ? 1 : 0 ) + QLatin1Char('\n'));}void QWSSoundClient::tryReadCommand(){ while ( canReadLine() ) { QString l = QString::fromAscii(readLine()); l.truncate(l.length()-1); // chomp QStringList token = l.split(QLatin1Char(' ')); if (token[0] == QLatin1String("SOUNDCOMPLETED")) { emit soundCompleted(token[1].toInt()); } else if (token[0] == QLatin1String("DEVICEREADY")) { emit deviceReady(token[1].toInt()); } else if (token[0] == QLatin1String("DEVICEERROR")) { emit deviceError(token[1].toInt(),(DeviceErrors)token[2].toInt()); } }}void QWSSoundClient::emitConnectionRefused(){ emit error( QTcpSocket::ConnectionRefusedError );}#endif#include "qsoundqss_qws.moc"#endif // QT_NO_SOUND
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -