mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	add card profile prober
This commit is contained in:
		
							parent
							
								
									b2b2eb1ee7
								
							
						
					
					
						commit
						b4d80462bf
					
				
					 4 changed files with 208 additions and 52 deletions
				
			
		| 
						 | 
					@ -920,7 +920,8 @@ if HAVE_ALSA
 | 
				
			||||||
modlibexec_LTLIBRARIES += \
 | 
					modlibexec_LTLIBRARIES += \
 | 
				
			||||||
		libalsa-util.la \
 | 
							libalsa-util.la \
 | 
				
			||||||
		module-alsa-sink.la \
 | 
							module-alsa-sink.la \
 | 
				
			||||||
		module-alsa-source.la
 | 
							module-alsa-source.la \
 | 
				
			||||||
 | 
							module-alsa-card.la
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if HAVE_SOLARIS
 | 
					if HAVE_SOLARIS
 | 
				
			||||||
| 
						 | 
					@ -1039,6 +1040,7 @@ SYMDEF_FILES = \
 | 
				
			||||||
		modules/oss/module-oss-symdef.h \
 | 
							modules/oss/module-oss-symdef.h \
 | 
				
			||||||
		modules/alsa/module-alsa-sink-symdef.h \
 | 
							modules/alsa/module-alsa-sink-symdef.h \
 | 
				
			||||||
		modules/alsa/module-alsa-source-symdef.h \
 | 
							modules/alsa/module-alsa-source-symdef.h \
 | 
				
			||||||
 | 
							modules/alsa/module-alsa-card-symdef.h \
 | 
				
			||||||
		modules/module-solaris-symdef.h \
 | 
							modules/module-solaris-symdef.h \
 | 
				
			||||||
		modules/module-waveout-symdef.h \
 | 
							modules/module-waveout-symdef.h \
 | 
				
			||||||
		modules/module-detect-symdef.h \
 | 
							modules/module-detect-symdef.h \
 | 
				
			||||||
| 
						 | 
					@ -1257,6 +1259,11 @@ module_alsa_source_la_LDFLAGS = $(MODULE_LDFLAGS)
 | 
				
			||||||
module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
 | 
					module_alsa_source_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
 | 
				
			||||||
module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 | 
					module_alsa_source_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module_alsa_card_la_SOURCES = modules/alsa/module-alsa-card.c
 | 
				
			||||||
 | 
					module_alsa_card_la_LDFLAGS = $(MODULE_LDFLAGS)
 | 
				
			||||||
 | 
					module_alsa_card_la_LIBADD = $(AM_LIBADD) $(ASOUNDLIB_LIBS) libalsa-util.la libpulsecore-@PA_MAJORMINORMICRO@.la libpulsecommon-@PA_MAJORMINORMICRO@.la libpulse.la
 | 
				
			||||||
 | 
					module_alsa_card_la_CFLAGS = $(AM_CFLAGS) $(ASOUNDLIB_CFLAGS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Solaris
 | 
					# Solaris
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module_solaris_la_SOURCES = modules/module-solaris.c
 | 
					module_solaris_la_SOURCES = modules/module-solaris.c
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -314,8 +314,8 @@ int pa_alsa_set_hw_params(
 | 
				
			||||||
        pa_bool_t require_exact_channel_number) {
 | 
					        pa_bool_t require_exact_channel_number) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int ret = -1;
 | 
					    int ret = -1;
 | 
				
			||||||
    snd_pcm_uframes_t _period_size = *period_size;
 | 
					    snd_pcm_uframes_t _period_size = period_size ? *period_size : 0;
 | 
				
			||||||
    unsigned int _periods = *periods;
 | 
					    unsigned int _periods = periods ? *periods : 0;
 | 
				
			||||||
    snd_pcm_uframes_t buffer_size;
 | 
					    snd_pcm_uframes_t buffer_size;
 | 
				
			||||||
    unsigned int r = ss->rate;
 | 
					    unsigned int r = ss->rate;
 | 
				
			||||||
    unsigned int c = ss->channels;
 | 
					    unsigned int c = ss->channels;
 | 
				
			||||||
| 
						 | 
					@ -327,8 +327,6 @@ int pa_alsa_set_hw_params(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(pcm_handle);
 | 
					    pa_assert(pcm_handle);
 | 
				
			||||||
    pa_assert(ss);
 | 
					    pa_assert(ss);
 | 
				
			||||||
    pa_assert(periods);
 | 
					 | 
				
			||||||
    pa_assert(period_size);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snd_pcm_hw_params_alloca(&hwparams);
 | 
					    snd_pcm_hw_params_alloca(&hwparams);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -361,10 +359,6 @@ int pa_alsa_set_hw_params(
 | 
				
			||||||
    if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0)
 | 
					    if ((ret = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &r, NULL)) < 0)
 | 
				
			||||||
        goto finish;
 | 
					        goto finish;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
 | 
					 | 
				
			||||||
    _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
 | 
					 | 
				
			||||||
    tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (require_exact_channel_number) {
 | 
					    if (require_exact_channel_number) {
 | 
				
			||||||
        if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0)
 | 
					        if ((ret = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, c)) < 0)
 | 
				
			||||||
            goto finish;
 | 
					            goto finish;
 | 
				
			||||||
| 
						 | 
					@ -373,50 +367,56 @@ int pa_alsa_set_hw_params(
 | 
				
			||||||
            goto finish;
 | 
					            goto finish;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_use_tsched) {
 | 
					 | 
				
			||||||
        _period_size = tsched_size;
 | 
					 | 
				
			||||||
        _periods = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size) == 0);
 | 
					 | 
				
			||||||
        pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    buffer_size = _periods * _period_size;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0)
 | 
					    if ((ret = snd_pcm_hw_params_set_periods_integer(pcm_handle, hwparams)) < 0)
 | 
				
			||||||
        goto finish;
 | 
					        goto finish;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_periods > 0) {
 | 
					    if (_period_size && tsched_size && _periods) {
 | 
				
			||||||
 | 
					        /* Adjust the buffer sizes, if we didn't get the rate we were asking for */
 | 
				
			||||||
 | 
					        _period_size = (snd_pcm_uframes_t) (((uint64_t) _period_size * r) / ss->rate);
 | 
				
			||||||
 | 
					        tsched_size = (snd_pcm_uframes_t) (((uint64_t) tsched_size * r) / ss->rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* First we pass 0 as direction to get exactly what we asked
 | 
					        if (_use_tsched) {
 | 
				
			||||||
         * for. That this is necessary is presumably a bug in ALSA */
 | 
					            _period_size = tsched_size;
 | 
				
			||||||
 | 
					            _periods = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        dir = 0;
 | 
					            pa_assert_se(snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size) == 0);
 | 
				
			||||||
        if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
 | 
					            pa_log_debug("Maximum hw buffer size is %u ms", (unsigned) buffer_size * 1000 / r);
 | 
				
			||||||
            dir = 1;
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        buffer_size = _periods * _period_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (_periods > 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            /* First we pass 0 as direction to get exactly what we asked
 | 
				
			||||||
 | 
					             * for. That this is necessary is presumably a bug in ALSA */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            dir = 0;
 | 
				
			||||||
            if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
 | 
					            if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
 | 
				
			||||||
                dir = -1;
 | 
					                dir = 1;
 | 
				
			||||||
                if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
 | 
					                if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0) {
 | 
				
			||||||
                    goto finish;
 | 
					                    dir = -1;
 | 
				
			||||||
 | 
					                    if ((ret = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &_periods, &dir)) < 0)
 | 
				
			||||||
 | 
					                        goto finish;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_period_size > 0)
 | 
					        if (_period_size > 0)
 | 
				
			||||||
        if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
 | 
					            if ((ret = snd_pcm_hw_params_set_buffer_size_near(pcm_handle, hwparams, &buffer_size)) < 0)
 | 
				
			||||||
            goto finish;
 | 
					                goto finish;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if  ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
 | 
					    if  ((ret = snd_pcm_hw_params(pcm_handle, hwparams)) < 0)
 | 
				
			||||||
        goto finish;
 | 
					        goto finish;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ss->rate != r)
 | 
					    if (ss->rate != r)
 | 
				
			||||||
        pa_log_warn("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
 | 
					        pa_log_info("Device %s doesn't support %u Hz, changed to %u Hz.", snd_pcm_name(pcm_handle), ss->rate, r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ss->channels != c)
 | 
					    if (ss->channels != c)
 | 
				
			||||||
        pa_log_warn("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
 | 
					        pa_log_info("Device %s doesn't support %u channels, changed to %u.", snd_pcm_name(pcm_handle), ss->channels, c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ss->format != f)
 | 
					    if (ss->format != f)
 | 
				
			||||||
        pa_log_warn("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
 | 
					        pa_log_info("Device %s doesn't support sample format %s, changed to %s.", snd_pcm_name(pcm_handle), pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((ret = snd_pcm_prepare(pcm_handle)) < 0)
 | 
					    if ((ret = snd_pcm_prepare(pcm_handle)) < 0)
 | 
				
			||||||
        goto finish;
 | 
					        goto finish;
 | 
				
			||||||
| 
						 | 
					@ -434,8 +434,11 @@ int pa_alsa_set_hw_params(
 | 
				
			||||||
    pa_assert(_periods > 0);
 | 
					    pa_assert(_periods > 0);
 | 
				
			||||||
    pa_assert(_period_size > 0);
 | 
					    pa_assert(_period_size > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *periods = _periods;
 | 
					    if (periods)
 | 
				
			||||||
    *period_size = _period_size;
 | 
					        *periods = _periods;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (period_size)
 | 
				
			||||||
 | 
					        *period_size = _period_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (use_mmap)
 | 
					    if (use_mmap)
 | 
				
			||||||
        *use_mmap = _use_mmap;
 | 
					        *use_mmap = _use_mmap;
 | 
				
			||||||
| 
						 | 
					@ -488,14 +491,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min) {
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct device_info {
 | 
					static const struct pa_alsa_profile_info device_table[] = {
 | 
				
			||||||
    pa_channel_map map;
 | 
					 | 
				
			||||||
    const char *alsa_name;
 | 
					 | 
				
			||||||
    const char *description;
 | 
					 | 
				
			||||||
    const char *name;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const struct device_info device_table[] = {
 | 
					 | 
				
			||||||
    {{ 1, { PA_CHANNEL_POSITION_MONO }},
 | 
					    {{ 1, { PA_CHANNEL_POSITION_MONO }},
 | 
				
			||||||
     "hw",
 | 
					     "hw",
 | 
				
			||||||
     "Analog Mono",
 | 
					     "Analog Mono",
 | 
				
			||||||
| 
						 | 
					@ -602,7 +598,6 @@ snd_pcm_t *pa_alsa_open_by_device_id(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    int direction = 1;
 | 
					    int direction = 1;
 | 
				
			||||||
    int err;
 | 
					 | 
				
			||||||
    char *d;
 | 
					    char *d;
 | 
				
			||||||
    snd_pcm_t *pcm_handle;
 | 
					    snd_pcm_t *pcm_handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -745,11 +740,8 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 | 
				
			||||||
    pa_bool_t reformat = FALSE;
 | 
					    pa_bool_t reformat = FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert(device);
 | 
					    pa_assert(device);
 | 
				
			||||||
    pa_assert(dev);
 | 
					 | 
				
			||||||
    pa_assert(ss);
 | 
					    pa_assert(ss);
 | 
				
			||||||
    pa_assert(map);
 | 
					    pa_assert(map);
 | 
				
			||||||
    pa_assert(nfrags);
 | 
					 | 
				
			||||||
    pa_assert(period_size);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    d = pa_xstrdup(device);
 | 
					    d = pa_xstrdup(device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -767,7 +759,7 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 | 
				
			||||||
                                SND_PCM_NO_AUTO_RESAMPLE|
 | 
					                                SND_PCM_NO_AUTO_RESAMPLE|
 | 
				
			||||||
                                SND_PCM_NO_AUTO_CHANNELS|
 | 
					                                SND_PCM_NO_AUTO_CHANNELS|
 | 
				
			||||||
                                (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
 | 
					                                (reformat ? 0 : SND_PCM_NO_AUTO_FORMAT))) < 0) {
 | 
				
			||||||
            pa_log("Error opening PCM device %s: %s", d, snd_strerror(err));
 | 
					            pa_log_info("Error opening PCM device %s: %s", d, snd_strerror(err));
 | 
				
			||||||
            pa_xfree(d);
 | 
					            pa_xfree(d);
 | 
				
			||||||
            return NULL;
 | 
					            return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -796,13 +788,14 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            pa_log("Failed to set hardware parameters on %s: %s", d, snd_strerror(err));
 | 
					            pa_log_info("Failed to set hardware parameters on %s: %s", d, snd_strerror(err));
 | 
				
			||||||
            pa_xfree(d);
 | 
					            pa_xfree(d);
 | 
				
			||||||
            snd_pcm_close(pcm_handle);
 | 
					            snd_pcm_close(pcm_handle);
 | 
				
			||||||
            return NULL;
 | 
					            return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        *dev = d;
 | 
					        if (dev)
 | 
				
			||||||
 | 
					            *dev = d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (ss->channels != map->channels)
 | 
					        if (ss->channels != map->channels)
 | 
				
			||||||
            pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
 | 
					            pa_channel_map_init_extend(map, ss->channels, PA_CHANNEL_MAP_ALSA);
 | 
				
			||||||
| 
						 | 
					@ -811,6 +804,93 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int pa_alsa_probe_profiles(
 | 
				
			||||||
 | 
					        const char *dev_id,
 | 
				
			||||||
 | 
					        const pa_sample_spec *ss,
 | 
				
			||||||
 | 
					        void (*cb)(const pa_alsa_profile_info *sink, const pa_alsa_profile_info *source, void *userdata),
 | 
				
			||||||
 | 
					        void *userdata) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const pa_alsa_profile_info *i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(dev_id);
 | 
				
			||||||
 | 
					    pa_assert(ss);
 | 
				
			||||||
 | 
					    pa_assert(cb);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* We try each combination of playback/capture. We also try to
 | 
				
			||||||
 | 
					     * open only for capture resp. only for sink. Don't get confused
 | 
				
			||||||
 | 
					     * by the trailing entry in device_table we use for this! */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = device_table; i < device_table + PA_ELEMENTSOF(device_table); i++) {
 | 
				
			||||||
 | 
					        const pa_alsa_profile_info *j;
 | 
				
			||||||
 | 
					        snd_pcm_t *pcm_i = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (i->alsa_name) {
 | 
				
			||||||
 | 
					            char *id;
 | 
				
			||||||
 | 
					            pa_sample_spec try_ss;
 | 
				
			||||||
 | 
					            pa_channel_map try_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pa_log_debug("Checking for playback on %s (%s)", i->name, i->alsa_name);
 | 
				
			||||||
 | 
					            id = pa_sprintf_malloc("%s:%s", i->alsa_name, dev_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try_ss = *ss;
 | 
				
			||||||
 | 
					            try_ss.channels = i->map.channels;
 | 
				
			||||||
 | 
					            try_map = i->map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pcm_i = pa_alsa_open_by_device_string(
 | 
				
			||||||
 | 
					                    id, NULL,
 | 
				
			||||||
 | 
					                    &try_ss, &try_map,
 | 
				
			||||||
 | 
					                    SND_PCM_STREAM_PLAYBACK,
 | 
				
			||||||
 | 
					                    NULL, NULL, 0, NULL, NULL,
 | 
				
			||||||
 | 
					                    TRUE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            pa_xfree(id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!pcm_i)
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (j = device_table; j < device_table + PA_ELEMENTSOF(device_table); j++) {
 | 
				
			||||||
 | 
					            snd_pcm_t *pcm_j = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (j->alsa_name) {
 | 
				
			||||||
 | 
					                char *jd;
 | 
				
			||||||
 | 
					                pa_sample_spec try_ss;
 | 
				
			||||||
 | 
					                pa_channel_map try_map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                pa_log_debug("Checking for capture on %s (%s)", j->name, j->alsa_name);
 | 
				
			||||||
 | 
					                jd = pa_sprintf_malloc("%s:%s", j->alsa_name, dev_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                try_ss = *ss;
 | 
				
			||||||
 | 
					                try_ss.channels = j->map.channels;
 | 
				
			||||||
 | 
					                try_map = j->map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                pcm_j = pa_alsa_open_by_device_string(
 | 
				
			||||||
 | 
					                        jd, NULL,
 | 
				
			||||||
 | 
					                        &try_ss, &try_map,
 | 
				
			||||||
 | 
					                        SND_PCM_STREAM_CAPTURE,
 | 
				
			||||||
 | 
					                        NULL, NULL, 0, NULL, NULL,
 | 
				
			||||||
 | 
					                        TRUE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                pa_xfree(jd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (!pcm_j)
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (pcm_j)
 | 
				
			||||||
 | 
					                snd_pcm_close(pcm_j);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cb(i->alsa_name ? i : NULL,
 | 
				
			||||||
 | 
					               j->alsa_name ? j : NULL, userdata);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (pcm_i)
 | 
				
			||||||
 | 
					            snd_pcm_close(pcm_i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
 | 
					int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev) {
 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +81,19 @@ snd_pcm_t *pa_alsa_open_by_device_string(
 | 
				
			||||||
        pa_bool_t *use_tsched,
 | 
					        pa_bool_t *use_tsched,
 | 
				
			||||||
        pa_bool_t require_exact_channel_number);
 | 
					        pa_bool_t require_exact_channel_number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct pa_alsa_profile_info {
 | 
				
			||||||
 | 
					    pa_channel_map map;
 | 
				
			||||||
 | 
					    const char *alsa_name;
 | 
				
			||||||
 | 
					    const char *description;
 | 
				
			||||||
 | 
					    const char *name;
 | 
				
			||||||
 | 
					} pa_alsa_profile_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int pa_alsa_probe_profiles(
 | 
				
			||||||
 | 
					        const char *dev_id,
 | 
				
			||||||
 | 
					        const pa_sample_spec *ss,
 | 
				
			||||||
 | 
					        void (*cb)(const pa_alsa_profile_info *sink, const pa_alsa_profile_info *source, void *userdata),
 | 
				
			||||||
 | 
					        void *userdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback);
 | 
					int pa_alsa_calc_mixer_map(snd_mixer_elem_t *elem, const pa_channel_map *channel_map, snd_mixer_selem_channel_id_t mixer_map[], pa_bool_t playback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void pa_alsa_dump(snd_pcm_t *pcm);
 | 
					void pa_alsa_dump(snd_pcm_t *pcm);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										56
									
								
								src/modules/alsa/module-alsa-card.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/modules/alsa/module-alsa-card.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,56 @@
 | 
				
			||||||
 | 
					/***
 | 
				
			||||||
 | 
					  This file is part of PulseAudio.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Copyright 2009 Lennart Poettering
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PulseAudio is free software; you can redistribute it and/or modify
 | 
				
			||||||
 | 
					  it under the terms of the GNU Lesser General Public License as published
 | 
				
			||||||
 | 
					  by the Free Software Foundation; either version 2 of the License,
 | 
				
			||||||
 | 
					  or (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  PulseAudio is distributed in the hope that it will be useful, but
 | 
				
			||||||
 | 
					  WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 | 
				
			||||||
 | 
					  General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  You should have received a copy of the GNU Lesser General Public License
 | 
				
			||||||
 | 
					  along with PulseAudio; if not, write to the Free Software
 | 
				
			||||||
 | 
					  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 | 
				
			||||||
 | 
					  USA.
 | 
				
			||||||
 | 
					***/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef HAVE_CONFIG_H
 | 
				
			||||||
 | 
					#include <config.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "alsa-util.h"
 | 
				
			||||||
 | 
					#include "module-alsa-card-symdef.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PA_MODULE_AUTHOR("Lennart Poettering");
 | 
				
			||||||
 | 
					PA_MODULE_DESCRIPTION("ALSA Card");
 | 
				
			||||||
 | 
					PA_MODULE_VERSION(PACKAGE_VERSION);
 | 
				
			||||||
 | 
					PA_MODULE_LOAD_ONCE(FALSE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void enumerate_cb(
 | 
				
			||||||
 | 
					        const pa_alsa_profile_info *sink,
 | 
				
			||||||
 | 
					        const pa_alsa_profile_info *source,
 | 
				
			||||||
 | 
					        void *userdata) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (sink && source)
 | 
				
			||||||
 | 
					        pa_log("Found Output %s + Input %s", sink->description, source->description);
 | 
				
			||||||
 | 
					    else if (sink)
 | 
				
			||||||
 | 
					        pa_log("Found Output %s", sink->description);
 | 
				
			||||||
 | 
					    else if (source)
 | 
				
			||||||
 | 
					        pa_log("Found Input %s", source->description);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int pa__init(pa_module*m) {
 | 
				
			||||||
 | 
					    pa_alsa_redirect_errors_inc();
 | 
				
			||||||
 | 
					    pa_alsa_probe_profiles("1", &m->core->default_sample_spec, enumerate_cb, m);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pa__done(pa_module*m) {
 | 
				
			||||||
 | 
					    pa_alsa_redirect_errors_dec();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue