AudioOutputSettings* AudioOutputNULL::GetOutputSettings(bool /*digital*/) { // Pretend that we support everything AudioFormat fmt; int rate; AudioOutputSettings *settings = new AudioOutputSettings(); while ((rate = settings->GetNextRate())) { settings->AddSupportedRate(rate); } while ((fmt = settings->GetNextFormat())) { settings->AddSupportedFormat(fmt); } for (uint channels = CHANNELS_MIN; channels <= CHANNELS_MAX; channels++) { settings->AddSupportedChannels(channels); } settings->setPassthrough(-1); // no passthrough return settings; }
AudioOutputSettings* AudioOutputOSS::GetOutputSettings(bool /*digital*/) { AudioOutputSettings *settings = new AudioOutputSettings(); QByteArray device = main_device.toLatin1(); audiofd = open(device.constData(), O_WRONLY | O_NONBLOCK); AudioFormat fmt; int rate, formats = 0; if (audiofd < 0) { VBERRENO(QString("Error opening audio device (%1)").arg(main_device)); delete settings; return NULL; } while ((rate = settings->GetNextRate())) { int rate2 = rate; if(ioctl(audiofd, SNDCTL_DSP_SPEED, &rate2) >= 0 && rate2 == rate) settings->AddSupportedRate(rate); } if(ioctl(audiofd, SNDCTL_DSP_GETFMTS, &formats) < 0) VBERRENO("Error retrieving formats"); else { int ofmt; while ((fmt = settings->GetNextFormat())) { switch (fmt) { case FORMAT_U8: ofmt = AFMT_U8; break; case FORMAT_S16: ofmt = AFMT_S16_NE; break; default: continue; } if (formats & ofmt) settings->AddSupportedFormat(fmt); } } #if defined(AFMT_AC3) // Check if drivers supports AC3 settings->setPassthrough(((formats & AFMT_AC3) != 0) - 1); #endif for (int i = 1; i <= 2; i++) { int channel = i; if (ioctl(audiofd, SNDCTL_DSP_CHANNELS, &channel) >= 0 && channel == i) { settings->AddSupportedChannels(i); } } close(audiofd); audiofd = -1; return settings; }
AudioOutputSettings* AudioOutputALSA::GetOutputSettings(bool passthrough) { snd_pcm_hw_params_t *params; snd_pcm_format_t afmt = SND_PCM_FORMAT_UNKNOWN; AudioFormat fmt; int rate; int err; AudioOutputSettings *settings = new AudioOutputSettings(); if (pcm_handle) { snd_pcm_close(pcm_handle); pcm_handle = NULL; } if ((err = TryOpenDevice(OPEN_FLAGS, passthrough)) < 0) { AERROR(QString("snd_pcm_open(\"%1\")").arg(m_lastdevice)); delete settings; return NULL; } snd_pcm_hw_params_alloca(¶ms); if ((err = snd_pcm_hw_params_any(pcm_handle, params)) < 0) { snd_pcm_close(pcm_handle); if ((err = TryOpenDevice(OPEN_FLAGS&FILTER_FLAGS, passthrough)) < 0) { AERROR(QString("snd_pcm_open(\"%1\")").arg(m_lastdevice)); delete settings; return NULL; } if ((err = snd_pcm_hw_params_any(pcm_handle, params)) < 0) { AERROR("No playback configurations available"); snd_pcm_close(pcm_handle); pcm_handle = NULL; delete settings; return NULL; } Warn("Supported audio format detection will be inacurrate " "(using plugin?)"); } while ((rate = settings->GetNextRate())) if(snd_pcm_hw_params_test_rate(pcm_handle, params, rate, 0) >= 0) settings->AddSupportedRate(rate); while ((fmt = settings->GetNextFormat())) { switch (fmt) { case FORMAT_U8: afmt = SND_PCM_FORMAT_U8; break; case FORMAT_S16: afmt = SND_PCM_FORMAT_S16; break; case FORMAT_S24: afmt = SND_PCM_FORMAT_S24; break; case FORMAT_S32: afmt = SND_PCM_FORMAT_S32; break; case FORMAT_FLT: afmt = SND_PCM_FORMAT_FLOAT; break; default: continue; } if (snd_pcm_hw_params_test_format(pcm_handle, params, afmt) >= 0) settings->AddSupportedFormat(fmt); } for (uint channels = CHANNELS_MIN; channels <= CHANNELS_MAX; channels++) if (snd_pcm_hw_params_test_channels(pcm_handle, params, channels) >= 0) settings->AddSupportedChannels(channels); snd_pcm_close(pcm_handle); pcm_handle = NULL; /* Check if name or description contains information to know if device can accept passthrough or not */ QMap<QString, QString> *alsadevs = GetALSADevices("pcm"); while(1) { QString real_device = (((passthru || enc) && m_discretedigital) ? passthru_device : main_device); QString desc = alsadevs->value(real_device); settings->setPassthrough(1); // yes passthrough if (real_device.contains("digital", Qt::CaseInsensitive) || desc.contains("digital", Qt::CaseInsensitive)) break; if (real_device.contains("iec958", Qt::CaseInsensitive)) break; if (real_device.contains("spdif", Qt::CaseInsensitive)) break; if (real_device.contains("hdmi", Qt::CaseInsensitive)) break; settings->setPassthrough(-1); // no passthrough // PulseAudio does not support passthrough if (real_device.contains("pulse", Qt::CaseInsensitive) || desc.contains("pulse", Qt::CaseInsensitive)) break; if (real_device.contains("analog", Qt::CaseInsensitive) || desc.contains("analog", Qt::CaseInsensitive)) break; if (real_device.contains("surround", Qt::CaseInsensitive) || desc.contains("surround", Qt::CaseInsensitive)) break; settings->setPassthrough(0); // maybe passthrough break; } delete alsadevs; return settings; }