mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	Add SPDIF/HDMI ALSA devices and device descriptions to device search table
This commit is contained in:
		
							parent
							
								
									33c22b0102
								
							
						
					
					
						commit
						4d4956ea2f
					
				
					 5 changed files with 189 additions and 78 deletions
				
			
		| 
						 | 
				
			
			@ -474,33 +474,81 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) {
 | 
			
		|||
 | 
			
		||||
struct device_info {
 | 
			
		||||
    pa_channel_map map;
 | 
			
		||||
    const char *alsa_name;
 | 
			
		||||
    const char *description;
 | 
			
		||||
    const char *name;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct device_info device_table[] = {
 | 
			
		||||
    {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } }, "front" },
 | 
			
		||||
    {{ 1, { PA_CHANNEL_POSITION_MONO }},
 | 
			
		||||
     "hw",
 | 
			
		||||
     "Analog Mono",
 | 
			
		||||
     "analog-mono" },
 | 
			
		||||
 | 
			
		||||
    {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
 | 
			
		||||
     "front",
 | 
			
		||||
     "Analog Stereo",
 | 
			
		||||
     "analog-stereo" },
 | 
			
		||||
 | 
			
		||||
    {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
 | 
			
		||||
     "iec958",
 | 
			
		||||
     "IEC958 Digital Stereo",
 | 
			
		||||
     "iec958-stereo" },
 | 
			
		||||
 | 
			
		||||
    {{ 2, { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT }},
 | 
			
		||||
     "hdmi",
 | 
			
		||||
     "HDMI Digital Stereo",
 | 
			
		||||
     "hdmi-stereo"},
 | 
			
		||||
 | 
			
		||||
    {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }}, "surround40" },
 | 
			
		||||
            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
 | 
			
		||||
     "surround40",
 | 
			
		||||
     "Analog Surround 4.0",
 | 
			
		||||
     "analog-surround-40" },
 | 
			
		||||
 | 
			
		||||
    {{ 4, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT }},
 | 
			
		||||
     "a52",
 | 
			
		||||
     "IEC958/AC3 Digital Surround 4.0",
 | 
			
		||||
     "iec958-ac3-surround-40" },
 | 
			
		||||
 | 
			
		||||
    {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_LFE }}, "surround41" },
 | 
			
		||||
            PA_CHANNEL_POSITION_LFE }},
 | 
			
		||||
     "surround41",
 | 
			
		||||
     "Analog Surround 4.1",
 | 
			
		||||
     "analog-surround-41"},
 | 
			
		||||
 | 
			
		||||
    {{ 5, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_CENTER }}, "surround50" },
 | 
			
		||||
            PA_CHANNEL_POSITION_CENTER }},
 | 
			
		||||
     "surround50",
 | 
			
		||||
     "Analog Surround 5.0",
 | 
			
		||||
     "analog-surround-50" },
 | 
			
		||||
 | 
			
		||||
    {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }}, "surround51" },
 | 
			
		||||
            PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE }},
 | 
			
		||||
     "surround51",
 | 
			
		||||
     "Analog Surround 5.1",
 | 
			
		||||
     "analog-surround-51" },
 | 
			
		||||
 | 
			
		||||
    {{ 6, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_CENTER,
 | 
			
		||||
            PA_CHANNEL_POSITION_FRONT_RIGHT, PA_CHANNEL_POSITION_REAR_LEFT,
 | 
			
		||||
            PA_CHANNEL_POSITION_REAR_RIGHT, PA_CHANNEL_POSITION_LFE}},
 | 
			
		||||
     "a52",
 | 
			
		||||
     "IEC958/AC3 Digital Surround 5.1",
 | 
			
		||||
     "iec958-ac3-surround-51" },
 | 
			
		||||
 | 
			
		||||
    {{ 8, { PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
 | 
			
		||||
            PA_CHANNEL_POSITION_CENTER, PA_CHANNEL_POSITION_LFE,
 | 
			
		||||
            PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }} , "surround71" },
 | 
			
		||||
            PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT }},
 | 
			
		||||
     "surround71",
 | 
			
		||||
     "Analog Surround 7.1",
 | 
			
		||||
     "analog-surround-71" },
 | 
			
		||||
 | 
			
		||||
    {{ 0, { 0 }}, NULL }
 | 
			
		||||
    {{ 0, { 0 }}, NULL, NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static pa_bool_t channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
 | 
			
		||||
| 
						 | 
				
			
			@ -532,7 +580,9 @@ snd_pcm_t *pa_alsa_open_by_device_id(
 | 
			
		|||
        snd_pcm_uframes_t *period_size,
 | 
			
		||||
        snd_pcm_uframes_t tsched_size,
 | 
			
		||||
        pa_bool_t *use_mmap,
 | 
			
		||||
        pa_bool_t *use_tsched) {
 | 
			
		||||
        pa_bool_t *use_tsched,
 | 
			
		||||
        const char**config_description,
 | 
			
		||||
        const char **config_name) {
 | 
			
		||||
 | 
			
		||||
    int i;
 | 
			
		||||
    int direction = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -554,90 +604,122 @@ snd_pcm_t *pa_alsa_open_by_device_id(
 | 
			
		|||
     * way, we iterate backwards, and check all devices that do not
 | 
			
		||||
     * provide a superset of the requested channel map.*/
 | 
			
		||||
 | 
			
		||||
    for (i = 0;; i += direction) {
 | 
			
		||||
    i = 0;
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        pa_sample_spec try_ss;
 | 
			
		||||
        pa_bool_t reformat;
 | 
			
		||||
 | 
			
		||||
        if (i < 0) {
 | 
			
		||||
            pa_assert(direction == -1);
 | 
			
		||||
        if ((direction > 0) == channel_map_superset(&device_table[i].map, map)) {
 | 
			
		||||
            pa_log_debug("Checking for %s (%s)", device_table[i].name, device_table[i].alsa_name);
 | 
			
		||||
 | 
			
		||||
            /* OK, so we iterated backwards, and now are at the
 | 
			
		||||
             * beginning of our list. */
 | 
			
		||||
            d = pa_sprintf_malloc("%s:%s", device_table[i].alsa_name, dev_id);
 | 
			
		||||
 | 
			
		||||
            break;
 | 
			
		||||
            reformat = FALSE;
 | 
			
		||||
            for (;;) {
 | 
			
		||||
                pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
 | 
			
		||||
 | 
			
		||||
        } else if (!device_table[i].name) {
 | 
			
		||||
            pa_assert(direction == 1);
 | 
			
		||||
                /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
 | 
			
		||||
                 * 1.0.17a would then ignore the SND_PCM_NO_xxx
 | 
			
		||||
                 * flags. Instead we enable nonblock mode afterwards via
 | 
			
		||||
                 * snd_pcm_nonblock(). Also see
 | 
			
		||||
                 * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
 | 
			
		||||
 | 
			
		||||
            /* OK, so we are at the end of our list. at iterated
 | 
			
		||||
             * forwards. */
 | 
			
		||||
 | 
			
		||||
            i--;
 | 
			
		||||
            direction = -1;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ((direction > 0) == !channel_map_superset(&device_table[i].map, map))
 | 
			
		||||
            continue;
 | 
			
		||||
 | 
			
		||||
        d = pa_sprintf_malloc("%s:%s", device_table[i].name, dev_id);
 | 
			
		||||
 | 
			
		||||
        reformat = FALSE;
 | 
			
		||||
        for (;;) {
 | 
			
		||||
            pa_log_debug("Trying %s %s SND_PCM_NO_AUTO_FORMAT ...", d, reformat ? "without" : "with");
 | 
			
		||||
 | 
			
		||||
            /* We don't pass SND_PCM_NONBLOCK here, since alsa-lib <=
 | 
			
		||||
             * 1.0.17a would then ignore the SND_PCM_NO_xxx
 | 
			
		||||
             * flags. Instead we enable nonblock mode afterwards via
 | 
			
		||||
             * snd_pcm_nonblock(). Also see
 | 
			
		||||
             * http://mailman.alsa-project.org/pipermail/alsa-devel/2008-August/010258.html */
 | 
			
		||||
 | 
			
		||||
            if ((err = snd_pcm_open(&pcm_handle, d, mode,
 | 
			
		||||
                                    /* SND_PCM_NONBLOCK| */
 | 
			
		||||
                                    SND_PCM_NO_AUTO_RESAMPLE|
 | 
			
		||||
                                    SND_PCM_NO_AUTO_CHANNELS|
 | 
			
		||||
                                    (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
 | 
			
		||||
                pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err));
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try_ss.channels = device_table[i].map.channels;
 | 
			
		||||
            try_ss.rate = ss->rate;
 | 
			
		||||
            try_ss.format = ss->format;
 | 
			
		||||
 | 
			
		||||
            if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) {
 | 
			
		||||
 | 
			
		||||
                if (!reformat) {
 | 
			
		||||
                    reformat = TRUE;
 | 
			
		||||
                    snd_pcm_close(pcm_handle);
 | 
			
		||||
                    continue;
 | 
			
		||||
                if ((err = snd_pcm_open(&pcm_handle, d, mode,
 | 
			
		||||
                                        /* SND_PCM_NONBLOCK| */
 | 
			
		||||
                                        SND_PCM_NO_AUTO_RESAMPLE|
 | 
			
		||||
                                        SND_PCM_NO_AUTO_CHANNELS|
 | 
			
		||||
                                        (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
 | 
			
		||||
                    pa_log_info("Couldn't open PCM device %s: %s", d, snd_strerror(err));
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
 | 
			
		||||
                    char *t;
 | 
			
		||||
                try_ss.channels = device_table[i].map.channels;
 | 
			
		||||
                try_ss.rate = ss->rate;
 | 
			
		||||
                try_ss.format = ss->format;
 | 
			
		||||
 | 
			
		||||
                    t = pa_sprintf_malloc("plug:%s", d);
 | 
			
		||||
                    pa_xfree(d);
 | 
			
		||||
                    d = t;
 | 
			
		||||
                if ((err = pa_alsa_set_hw_params(pcm_handle, &try_ss, nfrags, period_size, tsched_size, use_mmap, use_tsched, TRUE)) < 0) {
 | 
			
		||||
 | 
			
		||||
                    reformat = FALSE;
 | 
			
		||||
                    if (!reformat) {
 | 
			
		||||
                        reformat = TRUE;
 | 
			
		||||
                        snd_pcm_close(pcm_handle);
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (!pa_startswith(d, "plug:") && !pa_startswith(d, "plughw:")) {
 | 
			
		||||
                        char *t;
 | 
			
		||||
 | 
			
		||||
                        t = pa_sprintf_malloc("plug:%s", d);
 | 
			
		||||
                        pa_xfree(d);
 | 
			
		||||
                        d = t;
 | 
			
		||||
 | 
			
		||||
                        reformat = FALSE;
 | 
			
		||||
 | 
			
		||||
                        snd_pcm_close(pcm_handle);
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err));
 | 
			
		||||
                    snd_pcm_close(pcm_handle);
 | 
			
		||||
                    continue;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                pa_log_info("PCM device %s refused our hw parameters: %s", d, snd_strerror(err));
 | 
			
		||||
                snd_pcm_close(pcm_handle);
 | 
			
		||||
                break;
 | 
			
		||||
                *ss = try_ss;
 | 
			
		||||
                *map = device_table[i].map;
 | 
			
		||||
                pa_assert(map->channels == ss->channels);
 | 
			
		||||
                *dev = d;
 | 
			
		||||
                if (config_description)
 | 
			
		||||
                    *config_description = device_table[i].description;
 | 
			
		||||
                if (config_name)
 | 
			
		||||
                    *config_name = device_table[i].name;
 | 
			
		||||
 | 
			
		||||
                return pcm_handle;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            *ss = try_ss;
 | 
			
		||||
            *map = device_table[i].map;
 | 
			
		||||
            pa_assert(map->channels == ss->channels);
 | 
			
		||||
            *dev = d;
 | 
			
		||||
            return pcm_handle;
 | 
			
		||||
            pa_xfree(d);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        pa_xfree(d);
 | 
			
		||||
        if (direction > 0) {
 | 
			
		||||
            if (!device_table[i+1].alsa_name) {
 | 
			
		||||
                /* OK, so we are at the end of our list. Let's turn
 | 
			
		||||
                 * back. */
 | 
			
		||||
                direction = -1;
 | 
			
		||||
            } else {
 | 
			
		||||
                /* We are not at the end of the list, so let's simply
 | 
			
		||||
                 * try the next entry */
 | 
			
		||||
                i++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (direction < 0) {
 | 
			
		||||
 | 
			
		||||
            if (device_table[i+1].alsa_name &&
 | 
			
		||||
                device_table[i].map.channels == device_table[i+1].map.channels) {
 | 
			
		||||
 | 
			
		||||
                /* OK, the next entry has the same number of channels,
 | 
			
		||||
                 * let's try it */
 | 
			
		||||
                i++;
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                /* Hmm, so the next entry does not have the same
 | 
			
		||||
                 * number of channels, so let's go backwards until we
 | 
			
		||||
                 * find the next entry with a differnt number of
 | 
			
		||||
                 * channels */
 | 
			
		||||
 | 
			
		||||
                for (i--; i >= 0; i--)
 | 
			
		||||
                    if (device_table[i].map.channels != device_table[i+1].map.channels)
 | 
			
		||||
                        break;
 | 
			
		||||
 | 
			
		||||
                /* Hmm, there is no entry with a different number of
 | 
			
		||||
                 * entries, then we're done */
 | 
			
		||||
                if (i < 0)
 | 
			
		||||
                    break;
 | 
			
		||||
 | 
			
		||||
                /* OK, now lets find go back as long as we have the same number of channels */
 | 
			
		||||
                for (; i > 0; i--)
 | 
			
		||||
                    if (device_table[i].map.channels != device_table[i-1].map.channels)
 | 
			
		||||
                        break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* OK, we didn't find any good device, so let's try the raw plughw: stuff */
 | 
			
		||||
| 
						 | 
				
			
			@ -647,6 +729,11 @@ snd_pcm_t *pa_alsa_open_by_device_id(
 | 
			
		|||
    pcm_handle = pa_alsa_open_by_device_string(d, dev, ss, map, mode, nfrags, period_size, tsched_size, use_mmap, use_tsched);
 | 
			
		||||
    pa_xfree(d);
 | 
			
		||||
 | 
			
		||||
    if (pcm_handle) {
 | 
			
		||||
        *config_description = NULL;
 | 
			
		||||
        *config_name = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return pcm_handle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue