AudioOutputSettings* AudioOutputWin::GetOutputSettings(bool /*digital*/) { AudioOutputSettings *settings = new AudioOutputSettings(); // We use WAVE_MAPPER to find a compatible device, so just claim support // for all of the standard rates while (DWORD rate = (DWORD)settings->GetNextRate()) settings->AddSupportedRate(rate); // Support all standard formats settings->AddSupportedFormat(FORMAT_U8); settings->AddSupportedFormat(FORMAT_S16); #if 0 // 24-bit integer is not supported settings->AddSupportedFormat(FORMAT_S24); #endif #if 0 // 32-bit integer (OGG) is not supported on all platforms. settings->AddSupportedFormat(FORMAT_S32); #endif #if 0 // 32-bit floating point (AC3) is not supported on all platforms. settings->AddSupportedFormat(FORMAT_FLT); #endif // Guess that we can do up to 5.1 for (uint i = 2; i < 7; i++) settings->AddSupportedChannels(i); settings->setPassthrough(0); //Maybe passthrough return settings; }
void AudioConfigSettings::AudioAdvanced() { QString out = m_OutputDevice->getValue(); bool invalid = false; AudioOutputSettings settings; if (!audiodevs.contains(out)) { invalid = true; } else { settings = audiodevs.value(out).settings; } AudioAdvancedSettingsGroup audiosettings(invalid || (settings.canLPCM() && settings.canPassthrough() >= 0)); if (audiosettings.exec() == kDialogCodeAccepted) { AudioRescan(); UpdateCapabilities(QString::null); } }
void AudioConfigSettings::AudioAdvanced() { QString out = m_OutputDevice->getValue(); bool invalid = false; AudioOutputSettings settings; if (!audiodevs.contains(out)) { invalid = true; } else { settings = audiodevs.value(out).settings; } bool LPCM1 = settings.canFeature(FEATURE_LPCM) && gCoreContext->GetNumSetting("StereoPCM", false); AudioAdvancedSettingsGroup audiosettings(invalid || (settings.canPassthrough() >= 0)); if (audiosettings.exec() == kDialogCodeAccepted) { // Rescan audio list to check of override digital device AudioRescan(); bool LPCM2 = settings.canFeature(FEATURE_LPCM) && gCoreContext->GetNumSetting("StereoPCM", false); // restore speakers configure only of StereoPCM has changed and // we have LPCM capabilities UpdateCapabilities(QString::null, LPCM1 != LPCM2); } }
AudioOutputSettings* AudioOutputJACK::GetOutputSettings(bool /*digital*/) { int rate = 0; int i = 0; const char **matching_ports = NULL; AudioOutputSettings *settings = new AudioOutputSettings(); client = _jack_client_open(); if (!client) { JERROR(tr("Cannot start/connect to jack server " "(to check supported rate/channels)")); delete settings; return NULL; } if (client) rate = jack_get_sample_rate(client); if (!rate) { JERROR(tr("Unable to retrieve jack server sample rate")); goto err_out; } else settings->AddSupportedRate(rate); // Jack only wants float format samples (de-interleaved for preference) settings->AddSupportedFormat(FORMAT_FLT); // Find some Jack ports to connect to matching_ports = _jack_get_ports(); if (!matching_ports || !matching_ports[0]) { JERROR(tr("No ports available to connect to")); goto err_out; } // Count matching ports from 2nd port upwards i = 1; while (matching_ports[i] && (i < JACK_CHANNELS_MAX)) { settings->AddSupportedChannels(i+1); VBAUDIO(QString("Adding channels: %1").arg(i+1)); i++; } // Currently this looks very similar to error code - duplicated for safety free(matching_ports); _jack_client_close(&client); return settings; err_out: // Our abstracted exit point in case of error free(matching_ports); _jack_client_close(&client); delete settings; return NULL; }
AudioOutputSettings* AudioOutputDX::GetOutputSettings(bool passthrough) { AudioOutputSettings *settings = new AudioOutputSettings(); DSCAPS devcaps; devcaps.dwSize = sizeof(DSCAPS); m_priv->InitDirectSound(passthrough); if ((!m_priv->dsobject || !m_priv->dsound_dll) || FAILED(IDirectSound_GetCaps(m_priv->dsobject, &devcaps)) ) { delete settings; return nullptr; } VBAUDIO(QString("GetCaps sample rate min: %1 max: %2") .arg(devcaps.dwMinSecondarySampleRate) .arg(devcaps.dwMaxSecondarySampleRate)); /* We shouldn't assume we can do everything between min and max but there's no way to test individual rates, so we'll have to */ while (DWORD rate = (DWORD)settings->GetNextRate()) if((rate >= devcaps.dwMinSecondarySampleRate) || (rate <= devcaps.dwMaxSecondarySampleRate)) settings->AddSupportedRate(rate); /* We can only test for 8 and 16 bit support, DS uses float internally */ if (devcaps.dwFlags & DSCAPS_PRIMARY8BIT) settings->AddSupportedFormat(FORMAT_U8); if (devcaps.dwFlags & DSCAPS_PRIMARY16BIT) settings->AddSupportedFormat(FORMAT_S16); #if 0 // 24-bit integer is not supported settings->AddSupportedFormat(FORMAT_S24); #endif #if 0 // 32-bit integer (OGG) is not supported on all platforms. settings->AddSupportedFormat(FORMAT_S32); #endif #if 0 // 32-bit floating point (AC3) is not supported on all platforms. settings->AddSupportedFormat(FORMAT_FLT); #endif /* No way to test anything other than mono or stereo, guess that we can do up to 5.1 */ for (uint i = 2; i < 7; i++) settings->AddSupportedChannels(i); settings->setPassthrough(0); // Maybe passthrough return settings; }
/** * Returns capabilities supported by the audio device * amended to take into account the digital audio * options (AC3 and DTS) * Warning: do not call it twice in a row, will lead to invalid settings */ AudioOutputSettings* AudioOutputSettings::GetCleaned(bool newcopy) { AudioOutputSettings* aosettings; if (newcopy) { aosettings = new AudioOutputSettings; *aosettings = *this; } else aosettings = this; if (m_invalid) return aosettings; int mchannels = BestSupportedChannels(); if (mchannels > 2) { aosettings->setFeature(FEATURE_LPCM); } if (IsSupportedFormat(FORMAT_S16)) { // E-AC3 is transferred as stereo PCM at 4 times the rates // assume all amplifier supporting E-AC3 also supports 7.1 LPCM // as it's mandatory under the bluray standard //#if LIBAVFORMAT_VERSION_INT > AV_VERSION_INT( 52, 83, 0 ) if (IsSupportedChannels(8) && IsSupportedRate(192000)) aosettings->setFeature(FEATURE_TRUEHD | FEATURE_DTSHD | FEATURE_EAC3); //#endif if (m_passthrough >= 0) { if (mchannels == 2) { LOG(VB_AUDIO, LOG_INFO, "may be AC3 or DTS capable"); aosettings->AddSupportedChannels(6); } aosettings->setFeature(FEATURE_AC3 | FEATURE_DTS); } } return aosettings; }
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; }
AudioTestThread::AudioTestThread(QObject *parent, QString main, QString passthrough, int channels, AudioOutputSettings settings, bool hd) : MThread("AudioTest"), m_parent(parent), m_channels(channels), m_device(main), m_passthrough(passthrough), m_interrupted(false), m_channel(-1), m_hd(hd) { m_format = hd ? settings.BestSupportedFormat() : FORMAT_S16; m_samplerate = hd ? settings.BestSupportedRate() : 48000; m_audioOutput = AudioOutput::OpenAudio(m_device, m_passthrough, m_format, m_channels, 0, m_samplerate, AUDIOOUTPUT_VIDEO, true, false, 0, &settings); if (result().isEmpty()) { m_audioOutput->Pause(true); } }
AudioOutputSettings* AudioOutputCA::GetOutputSettings() { AudioOutputSettings *settings = new AudioOutputSettings(); // Seek hardware sample rate available int rate; int *rates = d->RatesList(d->mDeviceID); int *p_rates = rates; while (*p_rates > 0 && (rate = settings->GetNextRate())) { if (*p_rates == rate) { settings->AddSupportedRate(*p_rates); p_rates++; } } free(rates); // Supported format: 16 bits audio or float settings->AddSupportedFormat(FORMAT_S16); settings->AddSupportedFormat(FORMAT_FLT); bool *channels = d->ChannelsList(d->mDeviceID, passthru); if (channels == NULL) { // Error retrieving list of supported channels, assume stereo only settings->AddSupportedChannels(2); } else { for (int i = CHANNELS_MIN; i <= CHANNELS_MAX; i++) if (channels[i]) { Debug(QString("Support %1 channels").arg(i)); settings->AddSupportedChannels(i); } free(channels); } settings->setPassthrough(0); // Maybe passthrough return settings; }
AudioOutputSettings* AudioOutputWin::GetOutputSettings(void) { AudioOutputSettings *settings = new AudioOutputSettings(); // We use WAVE_MAPPER to find a compatible device, so just claim support // for all of the standard rates while (DWORD rate = (DWORD)settings->GetNextRate()) settings->AddSupportedRate(rate); // Support all standard formats settings->AddSupportedFormat(FORMAT_U8); settings->AddSupportedFormat(FORMAT_S16); settings->AddSupportedFormat(FORMAT_S24); settings->AddSupportedFormat(FORMAT_S32); settings->AddSupportedFormat(FORMAT_FLT); // Guess that we can do up to 5.1 for (uint i = 2; i < 7; i++) settings->AddSupportedChannels(i); settings->setPassthrough(0); //Maybe 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; }
/** * Returns capabilities supported by the audio device * amended to take into account the digital audio * options (AC3 and DTS) as well as the user settings * If newcopy = false, assume GetCleaned was called before hand */ AudioOutputSettings* AudioOutputSettings::GetUsers(bool newcopy) { AudioOutputSettings* aosettings; if (newcopy) aosettings = GetCleaned(newcopy); else aosettings = this; if (aosettings->m_invalid) return aosettings; int cur_channels = gCoreContext->GetNumSetting("MaxChannels", 2); int max_channels = aosettings->BestSupportedChannels(); bool bAC3 = aosettings->canFeature(FEATURE_AC3) && gCoreContext->GetNumSetting("AC3PassThru", false); bool bDTS = aosettings->canFeature(FEATURE_DTS) && gCoreContext->GetNumSetting("DTSPassThru", false); bool bLPCM = aosettings->canFeature(FEATURE_LPCM) && !gCoreContext->GetNumSetting("StereoPCM", false); bool bEAC3 = aosettings->canFeature(FEATURE_EAC3) && gCoreContext->GetNumSetting("EAC3PassThru", false) && !gCoreContext->GetNumSetting("Audio48kOverride", false); // TrueHD requires HBR support. bool bTRUEHD = aosettings->canFeature(FEATURE_TRUEHD) && gCoreContext->GetNumSetting("TrueHDPassThru", false) && !gCoreContext->GetNumSetting("Audio48kOverride", false) && gCoreContext->GetNumSetting("HBRPassthru", true); bool bDTSHD = aosettings->canFeature(FEATURE_DTSHD) && gCoreContext->GetNumSetting("DTSHDPassThru", false) && !gCoreContext->GetNumSetting("Audio48kOverride", false); if (max_channels > 2 && !bLPCM) max_channels = 2; if (max_channels == 2 && (bAC3 || bDTS)) max_channels = 6; if (cur_channels > max_channels) cur_channels = max_channels; aosettings->SetBestSupportedChannels(cur_channels); aosettings->setFeature(bAC3, FEATURE_AC3); aosettings->setFeature(bDTS, FEATURE_DTS); aosettings->setFeature(bLPCM, FEATURE_LPCM); aosettings->setFeature(bEAC3, FEATURE_EAC3); aosettings->setFeature(bTRUEHD, FEATURE_TRUEHD); aosettings->setFeature(bDTSHD, FEATURE_DTSHD); return aosettings; }
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; }
AudioOutputSettings AudioSetupWizard::UpdateCapabilities(bool restore, bool AC3) { QString out = m_audioDeviceButtonList->GetItemCurrent()->GetText(); int max_speakers = 8; int realmax_speakers = 8; AudioOutputSettings settings; for (AudioOutput::ADCVect::const_iterator it = m_outputlist->begin(); it != m_outputlist->end(); ++it) { if (it->name == out) { settings = it->settings; break; } } realmax_speakers = max_speakers = settings.BestSupportedChannels(); bool bAC3 = settings.canFeature(FEATURE_AC3); bool bDTS = settings.canFeature(FEATURE_DTS); bool bLPCM = settings.canFeature(FEATURE_LPCM); bool bEAC3 = settings.canFeature(FEATURE_EAC3); bool bTRUEHD = settings.canFeature(FEATURE_TRUEHD); bool bDTSHD = settings.canFeature(FEATURE_DTSHD); bAC3 ? m_ac3Check->Show() : m_ac3Check->Hide(); bDTS ? m_dtsCheck->Show() : m_dtsCheck->Hide(); bEAC3 ? m_eac3Check->Show() : m_eac3Check->Hide(); bTRUEHD ? m_truehdCheck->Show() : m_truehdCheck->Hide(); bDTSHD ? m_dtshdCheck->Show() : m_dtshdCheck->Hide(); bAC3 &= (m_ac3Check->GetCheckState() == MythUIStateType::Full); bDTS &= (m_dtsCheck->GetCheckState() == MythUIStateType::Full); if (max_speakers > 2 && !bLPCM) max_speakers = 2; if (max_speakers == 2 && bAC3) { max_speakers = 6; if (AC3) { restore = true; } } int cur_speakers = m_maxspeakers; if (m_speakerNumberButtonList->GetItemCurrent() != NULL) { cur_speakers = qVariantValue<int> (m_speakerNumberButtonList->GetItemCurrent()->GetData()); } if (cur_speakers > m_maxspeakers) { m_maxspeakers = cur_speakers; } if (restore) { cur_speakers = m_maxspeakers; } if (cur_speakers > max_speakers) { LOG(VB_AUDIO, LOG_INFO, QString("Reset device %1").arg(out)); cur_speakers = max_speakers; } // Remove everything and re-add available channels m_speakerNumberButtonList->Reset(); for (int i = 1; i <= max_speakers; i++) { if (settings.IsSupportedChannels(i)) { switch (i) { case 2: { MythUIButtonListItem *stereo = new MythUIButtonListItem(m_speakerNumberButtonList, QObject::tr("Stereo")); stereo->SetData(2); break; } case 6: { MythUIButtonListItem *sixchan = new MythUIButtonListItem(m_speakerNumberButtonList, QObject::tr("5.1 Channel Audio")); sixchan->SetData(6); break; } case 8: { MythUIButtonListItem *eightchan = new MythUIButtonListItem(m_speakerNumberButtonList, QObject::tr("7.1 Channel Audio")); eightchan->SetData(8); break; } default: continue; } } } m_speakerNumberButtonList->SetValueByData(qVariantFromValue(cur_speakers)); // Return values is used by audio test // where we mainly are interested by the number of channels // if we support AC3 and/or LPCM settings.SetBestSupportedChannels(cur_speakers); settings.setFeature(bAC3, FEATURE_AC3); settings.setFeature(bLPCM && realmax_speakers > 2, FEATURE_LPCM); return settings; }