Example #1
0
static int query_chmaps(snd_pcm_t *pcm)
{
    snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(pcm);
    snd_pcm_chmap_query_t **p, *v;

    if (!maps) {
        printf("Cannot query maps\n");
        return 1;
    }
    for (p = maps; (v = *p) != NULL; p++) {
        printf("Type = %s, Channels = %d\n",
               snd_pcm_chmap_type_name(v->type),
               v->map.channels);
        print_channels(&v->map);
    }
    snd_pcm_free_chmaps(maps);
    return 0;
}
Example #2
0
bool ALSAWriter::processParams(bool *paramsCorrected)
{
	const unsigned chn = getParam("chn").toUInt();
	const unsigned rate = getParam("rate").toUInt();
	const bool resetAudio = channels != chn || sample_rate != rate;
	channels = chn;
	sample_rate = rate;
	if (resetAudio || err)
	{
		snd_pcm_hw_params_t *params;
		snd_pcm_hw_params_alloca(&params);

		close();

		QString chosenDevName = devName;
		if (autoFindMultichannelDevice && channels > 2)
		{
			bool mustAutoFind = true, forceStereo = false;
			if (!snd_pcm_open(&snd, chosenDevName.toLocal8Bit(), SND_PCM_STREAM_PLAYBACK, 0))
			{
				if (snd_pcm_type(snd) == SND_PCM_TYPE_HW)
				{
					unsigned max_chn = 0;
					snd_pcm_hw_params_any(snd, params);
					mustAutoFind = snd_pcm_hw_params_get_channels_max(params, &max_chn) || max_chn < channels;
				}
#ifdef HAVE_CHMAP
				else if (paramsCorrected)
				{
					snd_pcm_chmap_query_t **chmaps = snd_pcm_query_chmaps(snd);
					if (chmaps)
						snd_pcm_free_chmaps(chmaps);
					else
						forceStereo = true;
				}
#endif
				snd_pcm_close(snd);
				snd = NULL;
			}
			if (mustAutoFind)
			{
				QString newDevName;
				if (channels <= 4)
					newDevName = "surround40";
				else if (channels <= 6)
					newDevName = "surround51";
				else
					newDevName = "surround71";
				if (!newDevName.isEmpty() && newDevName != chosenDevName)
				{
					if (ALSACommon::getDevices().first.contains(newDevName))
						chosenDevName = newDevName;
					else if (forceStereo)
					{
						channels = 2;
						*paramsCorrected = true;
					}
				}
			}
		}
		if (!chosenDevName.isEmpty())
		{
			bool sndOpen = !snd_pcm_open(&snd, chosenDevName.toLocal8Bit(), SND_PCM_STREAM_PLAYBACK, 0);
			if (devName != chosenDevName)
			{
				if (sndOpen)
					QMPlay2Core.logInfo("ALSA :: " + devName + "\" -> \"" + chosenDevName + "\"");
				else
				{
					sndOpen = !snd_pcm_open(&snd, devName.toLocal8Bit(), SND_PCM_STREAM_PLAYBACK, 0);
					QMPlay2Core.logInfo("ALSA :: " + tr("Cannot open") + " \"" + chosenDevName + "\", " + tr("back to") + " \"" + devName + "\"");
				}
			}
			if (sndOpen)
			{
				snd_pcm_hw_params_any(snd, params);

				snd_pcm_format_t fmt = SND_PCM_FORMAT_UNKNOWN;
				if (!snd_pcm_hw_params_test_format(snd, params, SND_PCM_FORMAT_S32))
				{
					fmt = SND_PCM_FORMAT_S32;
					sample_size = 4;
				}
				else if (!snd_pcm_hw_params_test_format(snd, params, SND_PCM_FORMAT_S16))
				{
					fmt = SND_PCM_FORMAT_S16;
					sample_size = 2;
				}
				else if (!snd_pcm_hw_params_test_format(snd, params, SND_PCM_FORMAT_S8))
				{
					fmt = SND_PCM_FORMAT_S8;
					sample_size = 1;
				}

				unsigned delay_us = round(delay * 1000000.0);
				if (fmt != SND_PCM_FORMAT_UNKNOWN && set_snd_pcm_hw_params(snd, params, fmt, channels, sample_rate, delay_us))
				{
					bool err2 = false;
					if (channels != chn || sample_rate != rate)
					{
						if (paramsCorrected)
							*paramsCorrected = true;
						else
							err2 = true;
					}
					if (!err2)
					{
						err2 = snd_pcm_hw_params(snd, params);
						if (err2 && paramsCorrected) //jakiś błąd, próba zmiany sample_rate
						{
							snd_pcm_hw_params_any(snd, params);
							err2 = snd_pcm_hw_params_set_rate_resample(snd, params, false) || !set_snd_pcm_hw_params(snd, params, fmt, channels, sample_rate, delay_us) || snd_pcm_hw_params(snd, params);
							if (!err2)
								*paramsCorrected = true;
						}
						if (!err2)
						{
							modParam("delay", delay_us / 1000000.0);
							if (paramsCorrected && *paramsCorrected)
							{
								modParam("chn", channels);
								modParam("rate", sample_rate);
							}

							canPause = snd_pcm_hw_params_can_pause(params) && snd_pcm_hw_params_can_resume(params);

							mustSwapChn = channels == 6 || channels == 8;
#ifdef HAVE_CHMAP
							if (mustSwapChn)
							{
								snd_pcm_chmap_query_t **chmaps = snd_pcm_query_chmaps(snd);
								if (chmaps)
								{
									for (int i = 0; chmaps[i]; ++i)
									{
										if (chmaps[i]->map.channels >= channels)
										{
											for (uint j = 0; j < channels; ++j)
											{
												mustSwapChn &= chmaps[i]->map.pos[j] == j + SND_CHMAP_FL;
												if (!mustSwapChn)
													break;
											}
											break;
										}
									}
									snd_pcm_free_chmaps(chmaps);
								}
							}
#endif
							return true;
						}
					}
				}
			}
		}
		err = true;
		QMPlay2Core.logError("ALSA :: " + tr("Cannot open audio output stream"));
	}

	return readyWrite();
}