static int elem_get_vol_percent(snd_mixer_elem_t *elem) { int i, percent; long pmin, pmax, volume; for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) { /* playback volume */ if (snd_mixer_selem_has_playback_channel(elem, i) && !snd_mixer_selem_has_common_volume(elem)) { snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); if (snd_mixer_selem_has_playback_volume(elem)) snd_mixer_selem_get_playback_volume(elem, i, &volume); } /* capture volume */ else if (snd_mixer_selem_has_capture_channel(elem, i) && !snd_mixer_selem_has_common_volume(elem)) { snd_mixer_selem_get_capture_volume_range(elem, &pmin, &pmax); if (snd_mixer_selem_has_capture_volume(elem)) snd_mixer_selem_get_capture_volume(elem, i, &volume); } else { /* Misc. ex: Boost */ snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); snd_mixer_selem_get_playback_volume(elem, i, &volume); } } percent = (int) ((double)(volume - pmin) / (double)(pmax - pmin) * 100); return percent; }
static PxVolume get_volume_indexed(PxDev *dev, int i, int playback) { snd_mixer_elem_t *elem; long vol, min, max; if (!dev->handle) { return 0.0; } if (i < 0 || i > dev->numselems) { return 0.0; } elem = dev->selems[i].elem; if (playback) { snd_mixer_selem_get_playback_volume_range(elem, &min, &max); if (snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT)) { snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &vol); return (PxVolume) vol / (max - min); } } else { snd_mixer_selem_get_capture_volume_range(elem, &min, &max); if (snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT)) { snd_mixer_selem_get_capture_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &vol); return (PxVolume) vol / (max - min); } } return 0.0; }
static void elem_set_vol_percent(snd_mixer_elem_t *elem, int vol_percent) { int i; long pmin, pmax, value; //sdbg("%s: set mixer element volume\n", __func__); for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) { if (snd_mixer_selem_has_playback_channel(elem, i) && !snd_mixer_selem_has_common_volume(elem)) { snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); /* playback volume */ if (snd_mixer_selem_has_playback_volume(elem)) { value = (int)rint((double)pmin + 0.01 * vol_percent * ((double)pmax - (double)pmin)); snd_mixer_selem_set_playback_volume(elem, i, value); } } else if (snd_mixer_selem_has_capture_channel(elem, i) && !snd_mixer_selem_has_common_volume(elem)) { /* capture volume */ snd_mixer_selem_get_capture_volume_range(elem, &pmin, &pmax); if (snd_mixer_selem_has_capture_volume(elem)) { value = (int)rint((double)pmin + 0.01 * vol_percent * ((double)pmax - (double)pmin)); snd_mixer_selem_set_capture_volume(elem, i, value); } } else { /* Misc. ex: Boost */ snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); value = (int)rint((double)pmin + 0.01 * vol_percent * ((double)pmax - (double)pmin)); snd_mixer_selem_set_playback_volume(elem, i, value); snd_mixer_selem_get_capture_volume_range(elem, &pmin, &pmax); value = (int)rint((double)pmin + 0.01 * vol_percent * ((double)pmax - (double)pmin)); snd_mixer_selem_set_capture_volume(elem, i, value); } } }
static enum MixerCode alsaMixerSelectCard(struct MixerSystem* system, int mixerId) { enum MixerCode code; snd_mixer_elem_t* mixerElem = NULL; AlsaMixerCard* card = (AlsaMixerCard*)system->active; if ( !card ) { if ( card == system->mixerCard->pElement[mixerId] ) { return MIXER_CODE_OK; } alsaMixerCardClose(system); } code = commonMixerSelectCard(system, mixerId); if ( code != MIXER_CODE_OK ) { GOC_DEBUG("Cannot select card by commonMixerSelectCard"); return code; } card = (AlsaMixerCard*)system->active; GOC_CHEOP_DEBUG(snd_mixer_open( &card->sndmixer, 0 ) == 0, return MIXER_CODE_CANNOT_OPEN_CARD); GOC_CHEOP_DEBUG(snd_mixer_attach( card->sndmixer, card->physicalName ) == 0, return MIXER_CODE_CANNOT_OPEN_CARD); GOC_CHEOP_DEBUG(snd_mixer_selem_register( card->sndmixer, NULL, NULL ) == 0, return MIXER_CODE_CANNOT_OPEN_CARD); GOC_CHEOP_DEBUG(snd_mixer_load( card->sndmixer ) == 0, return MIXER_CODE_CANNOT_OPEN_CARD); mixerElem = snd_mixer_first_elem( card->sndmixer ); while ( mixerElem ) { AlsaMixerElement* pMixerElement = alsaMixerElementAlloc(); for (int channel = 0; channel <= SND_MIXER_SCHN_LAST; channel++ ) { if ( snd_mixer_selem_has_playback_channel(mixerElem, channel) && snd_mixer_selem_get_playback_volume_range(mixerElem, &pMixerElement->rangemin, &pMixerElement->rangemax) == 0 && snd_mixer_selem_get_playback_volume(mixerElem, channel, &pMixerElement->volume) == 0 ) { pMixerElement->name = goc_stringCopy(NULL, snd_mixer_selem_get_name(mixerElem)); pMixerElement->type = MIXER_ELEMENT_PLAYBACK; pMixerElement->sndelement = mixerElem; card->mixerElement = goc_arrayAdd( card->mixerElement, pMixerElement ); break; } else if ( snd_mixer_selem_has_capture_channel(mixerElem, channel) && snd_mixer_selem_get_capture_volume_range(mixerElem, &pMixerElement->rangemin, &pMixerElement->rangemax) == 0 && snd_mixer_selem_get_capture_volume(mixerElem, channel, &pMixerElement->volume) == 0 ) { pMixerElement->name = goc_stringCopy(NULL, snd_mixer_selem_get_name(mixerElem)); pMixerElement->type = MIXER_ELEMENT_CAPTURE; pMixerElement->sndelement = mixerElem; card->mixerElement = goc_arrayAdd( card->mixerElement, pMixerElement ); break; } } mixerElem = snd_mixer_elem_next( mixerElem ); } return MIXER_CODE_OK; }
static int elem_get_status(snd_mixer_elem_t *elem) { int i, psw = -1; for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) { if (snd_mixer_selem_has_playback_channel(elem, i) && snd_mixer_selem_has_playback_switch(elem)) snd_mixer_selem_get_playback_switch(elem, i, &psw); else if (snd_mixer_selem_has_capture_channel(elem, i) && snd_mixer_selem_has_capture_switch(elem)) snd_mixer_selem_get_capture_switch(elem, i, &psw); } return psw; }
/* * Class: org_tritonus_lowlevel_alsa_AlsaMixerElement * Method: hasPlaybackChannel * Signature: (I)Z */ JNIEXPORT jboolean JNICALL Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasPlaybackChannel (JNIEnv* env, jobject obj, jint nChannelType) { snd_mixer_elem_t* handle; int nReturn; if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasPlaybackChannel(): begin\n"); } handle = getHandle(env, obj); nReturn = snd_mixer_selem_has_playback_channel(handle, (snd_mixer_selem_channel_id_t) nChannelType); if (debug_flag) { (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasPlaybackChannel(): end\n"); } return (jboolean) nReturn; }
static PyObject* ALSAAudio_get_volume(output_ALSAAudio *self, PyObject *args) { if (self->mixer_elem) { /*get the average volume from all supported output channels*/ const snd_mixer_selem_channel_id_t channels[] = { SND_MIXER_SCHN_FRONT_LEFT, SND_MIXER_SCHN_FRONT_RIGHT, SND_MIXER_SCHN_REAR_LEFT, SND_MIXER_SCHN_REAR_RIGHT, SND_MIXER_SCHN_FRONT_CENTER, SND_MIXER_SCHN_WOOFER, SND_MIXER_SCHN_SIDE_LEFT, SND_MIXER_SCHN_SIDE_RIGHT, SND_MIXER_SCHN_REAR_CENTER}; const size_t channel_count = sizeof(channels) / sizeof(snd_mixer_selem_channel_id_t); size_t i; double total_volume = 0.0; unsigned total_channels = 0; for (i = 0; i < channel_count; i++) { long channel_volume; if (snd_mixer_selem_has_playback_channel(self->mixer_elem, channels[i]) && (snd_mixer_selem_get_playback_volume(self->mixer_elem, channels[i], &channel_volume) == 0)) { total_volume += channel_volume; total_channels++; } } if (total_channels > 0) { const double average_volume = total_volume / total_channels; /*convert to range min_volume->max_volume*/ return PyFloat_FromDouble(average_volume / self->volume_max); } else { return PyFloat_FromDouble(0.0); } } else { return PyFloat_FromDouble(0.0); } }
static int alsa_read_mixer_raw (snd_mixer_elem_t *elem) { if (mixer_handle) { long volume = 0; int nchannels = 0; int i; int err; assert (elem != NULL); handle_mixer_events (mixer_handle); for (i = 0; i < SND_MIXER_SCHN_LAST; i++) if (snd_mixer_selem_has_playback_channel(elem, 1 << i)) { long vol; nchannels++; if ((err = snd_mixer_selem_get_playback_volume( elem, 1 << i, &vol)) < 0) { error ("Can't read mixer: %s", snd_strerror(err)); return -1; } /*logit ("Vol %d: %ld", i, vol);*/ volume += vol; } if (nchannels > 0) volume /= nchannels; else { logit ("Mixer has no channels"); volume = -1; } /*logit ("Max: %ld, Min: %ld", mixer_max, mixer_min);*/ return volume; } else return -1; }
static gint _j4status_alsa_section_mixer_callback(snd_mixer_t *mixer, guint mask, snd_mixer_elem_t *elem) { J4statusAlsaSection *section = snd_mixer_get_callback_private(mixer); if ( mask & SND_CTL_EVENT_MASK_ADD ) { if ( ( snd_mixer_selem_get_index(elem) == 0 ) && ( g_strcmp0(snd_mixer_selem_get_name(elem), "Master") == 0 ) && snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) && ( snd_mixer_elem_get_callback_private(elem) == NULL ) ) { snd_mixer_elem_set_callback(elem, _j4status_alsa_section_elem_callback); snd_mixer_elem_set_callback_private(elem, section); } } return 0; }
static int set_normalized_volume_all(snd_mixer_elem_t *elem, double volume, int dir, enum ctl_dir ctl_dir) { snd_mixer_selem_channel_id_t chn; int err; for (chn = 0; chn < 32; chn++) { if (!snd_mixer_selem_has_playback_channel(elem, chn)) continue; err = set_normalized_volume(elem, chn, volume, dir, ctl_dir); if (err < 0) return err; if (chn == 0 && snd_mixer_selem_has_playback_volume_joined(elem)) return 0; } return 0; }
/* mute: 0 -> mute, 1 -> unmute */ void sound_mixer_mute(const char *mixer, MUTEST mute) { int i; snd_mixer_t *handle = NULL; snd_mixer_elem_t *elem = NULL; elem = sound_get_elem(mixer, &handle); if (!elem) return; for (i = 0; i <= SND_MIXER_SCHN_LAST; i++) { if (snd_mixer_selem_has_playback_channel(elem, i) && snd_mixer_selem_has_playback_switch(elem)) snd_mixer_selem_set_playback_switch(elem, i, mute); else if (snd_mixer_selem_has_capture_channel(elem, i) && snd_mixer_selem_has_capture_switch(elem)) snd_mixer_selem_set_capture_switch(elem, i, mute); } snd_mixer_close(handle); }
static void _j4status_alsa_section_update(J4statusAlsaSection *section, snd_mixer_elem_t *elem) { if ( ( ! snd_mixer_selem_has_playback_volume(elem) ) || ( ! snd_mixer_selem_has_playback_switch(elem) ) || ( ! snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) ) ) return; int error; gboolean pswitch = TRUE; error = snd_mixer_selem_get_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, &pswitch); if ( error < 0 ) g_warning("Couldn't get muted status: %s", snd_strerror(error)); else { if ( pswitch ) j4status_section_set_state(section->section, J4STATUS_STATE_GOOD); else j4status_section_set_state(section->section, J4STATUS_STATE_BAD); } glong volume = 0; if ( section->use_dB ) error = snd_mixer_selem_get_playback_dB(elem, SND_MIXER_SCHN_FRONT_LEFT, &volume); else error = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &volume); if ( error < 0 ) g_warning("Couldn't get volume: %s", snd_strerror(error)); else { guint8 vol; gchar *v; vol = _j4status_alsa_get_normalized_volume(volume, section->min, section->max, section->use_dB); v = g_strdup_printf("%hu%%", vol); j4status_section_set_value(section->section, v); } }
static void set_volume_indexed(PxDev *dev, int i, PxVolume volume, int playback) { snd_mixer_elem_t *elem; long vol, min, max; int j; if (!dev->handle) { return; } if (i < 0 || i > dev->numselems) { return; } elem = dev->selems[i].elem; if (playback) { snd_mixer_selem_get_playback_volume_range(elem, &min, &max); for (j = 0; j < SND_MIXER_SCHN_LAST; j++) { if (snd_mixer_selem_has_playback_channel(elem, j)) { vol = (long) (volume * (max - min) + 0.5); snd_mixer_selem_set_playback_volume(elem, j, vol); } } } else { snd_mixer_selem_get_capture_volume_range(elem, &min, &max); for (j = 0; j < SND_MIXER_SCHN_LAST; j++) { if (snd_mixer_selem_has_capture_channel(elem, j)) { vol = (long) (volume * (max - min) + 0.5); snd_mixer_selem_set_capture_volume(elem, j, vol); } } } return; }
void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) { PortMixer* portMixer; snd_mixer_elem_t* elem; void* control; PortControl* portControl; void* controls[10]; int numControls; char* portName; int isPlayback = 0; int isMono; int isStereo; char* type; snd_mixer_selem_channel_id_t channel; TRACE0("> PORT_GetControls\n"); if (id == NULL) { ERROR0("Invalid handle!"); // $$mp: an error code should be returned. return; } portMixer = (PortMixer*) id; if (portIndex < 0 || portIndex >= portMixer->numElems) { ERROR0("Port index out of range!"); // $$mp: an error code should be returned. return; } numControls = 0; elem = portMixer->elems[portIndex]; if (snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) { /* Since we've split/duplicated elements with both playback and capture on the recovery of elements, we now can assume that we handle only to deal with either playback or capture. */ isPlayback = isPlaybackFunction(portMixer->types[portIndex]); isMono = (isPlayback && snd_mixer_selem_is_playback_mono(elem)) || (!isPlayback && snd_mixer_selem_is_capture_mono(elem)); isStereo = (isPlayback && snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) && snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) || (!isPlayback && snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) && snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)); // single volume control if (isMono || isStereo) { if (getControlSlot(portMixer, &portControl)) { portControl->elem = elem; portControl->portType = portMixer->types[portIndex]; portControl->controlType = CONTROL_TYPE_VOLUME; if (isMono) { portControl->channel = CHANNELS_MONO; } else { portControl->channel = CHANNELS_STEREO; } control = createVolumeControl(creator, portControl, elem, isPlayback); if (control != NULL) { controls[numControls++] = control; } } } else { // more than two channels, each channels has its own control. for (channel = SND_MIXER_SCHN_FRONT_LEFT; channel <= SND_MIXER_SCHN_LAST; channel++) { if ((isPlayback && snd_mixer_selem_has_playback_channel(elem, channel)) || (!isPlayback && snd_mixer_selem_has_capture_channel(elem, channel))) { if (getControlSlot(portMixer, &portControl)) { portControl->elem = elem; portControl->portType = portMixer->types[portIndex]; portControl->controlType = CONTROL_TYPE_VOLUME; portControl->channel = channel; control = createVolumeControl(creator, portControl, elem, isPlayback); // We wrap in a compound control to provide the channel name. if (control != NULL) { /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the declaration of PORT_NewCompoundControlPtr in Ports.h should be changed to take a const char* parameter. */ control = (creator->newCompoundControl)(creator, (char*) snd_mixer_selem_channel_name(channel), &control, 1); } if (control != NULL) { controls[numControls++] = control; } } } } } // BALANCE control if (isStereo) { if (getControlSlot(portMixer, &portControl)) { portControl->elem = elem; portControl->portType = portMixer->types[portIndex]; portControl->controlType = CONTROL_TYPE_BALANCE; portControl->channel = CHANNELS_STEREO; /* $$mp: The value for precision is chosen more or less arbitrarily. */ control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_BALANCE, -1.0F, 1.0F, 0.01F, ""); if (control != NULL) { controls[numControls++] = control; } } } } if (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_capture_switch(elem)) { if (getControlSlot(portMixer, &portControl)) { type = isPlayback ? CONTROL_TYPE_MUTE : CONTROL_TYPE_SELECT; portControl->elem = elem; portControl->portType = portMixer->types[portIndex]; portControl->controlType = type; control = (creator->newBooleanControl)(creator, portControl, type); if (control != NULL) { controls[numControls++] = control; } } } /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the declaration of PORT_NewCompoundControlPtr in Ports.h should be changed to take a const char* parameter. */ portName = (char*) snd_mixer_selem_get_name(elem); control = (creator->newCompoundControl)(creator, portName, controls, numControls); if (control != NULL) { (creator->addControl)(creator, control); } TRACE0("< PORT_GetControls\n"); }
GstMixerTrack * gst_alsa_mixer_track_new (snd_mixer_elem_t * element, gint num, gint track_num, gint flags, gboolean sw, GstAlsaMixerTrack * shared_mute_track, gboolean append_capture) { GstAlsaMixerTrack *alsa_track; GstMixerTrack *track; const gchar *name; const gchar *label; gint i; long min = 0, max = 0; const struct { const gchar orig[12]; const gchar trans[12]; } alsa_track_labels[] = { { "Master", N_("Master")}, { "Bass", N_("Bass")}, { "Treble", N_("Treble")}, { "PCM", N_("PCM")}, { "Synth", N_("Synth")}, { "Line", N_("Line-in")}, { "CD", N_("CD")}, { "Mic", N_("Microphone")}, { "PC Speaker", N_("PC Speaker")}, { "Playback", N_("Playback")}, { "Capture", N_("Capture")} }; name = snd_mixer_selem_get_name (element); GST_LOG ("[%s] num=%d,track_num=%d,flags=0x%08x,sw=%s,shared_mute_track=%p", name, num, track_num, flags, (sw) ? "true" : "false", shared_mute_track); track = (GstMixerTrack *) g_object_new (GST_ALSA_MIXER_TRACK_TYPE, "untranslated-label", name, NULL); alsa_track = (GstAlsaMixerTrack *) track; GST_LOG ("[%s] created new mixer track %p", name, track); /* This reflects the assumptions used for GstAlsaMixerTrack */ if (!(!!(flags & GST_MIXER_TRACK_OUTPUT) ^ !!(flags & GST_MIXER_TRACK_INPUT))) { GST_ERROR ("Mixer track must be either output or input!"); g_return_val_if_reached (NULL); } track->flags = flags; alsa_track->element = element; alsa_track->shared_mute = shared_mute_track; alsa_track->track_num = track_num; alsa_track->alsa_channels = 0; gst_alsa_mixer_track_update_alsa_capabilities (alsa_track); if (flags & GST_MIXER_TRACK_OUTPUT) { while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS && snd_mixer_selem_has_playback_channel (element, alsa_track->alsa_channels)) { alsa_track->alsa_channels++; } GST_LOG ("[%s] %d output channels", name, alsa_track->alsa_channels); } else if (flags & GST_MIXER_TRACK_INPUT) { while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS && snd_mixer_selem_has_capture_channel (element, alsa_track->alsa_channels)) { alsa_track->alsa_channels++; } GST_LOG ("[%s] %d input channels", name, alsa_track->alsa_channels); } else { g_assert_not_reached (); } if (sw) track->num_channels = 0; else track->num_channels = alsa_track->alsa_channels; /* translate the name if we can */ label = name; for (i = 0; i < G_N_ELEMENTS (alsa_track_labels); ++i) { if (g_utf8_collate (label, alsa_track_labels[i].orig) == 0) { label = _(alsa_track_labels[i].trans); break; } } if (num == 0) { track->label = g_strdup_printf ("%s%s%s", label, append_capture ? " " : "", append_capture ? _("Capture") : ""); } else { track->label = g_strdup_printf ("%s%s%s %d", label, append_capture ? " " : "", append_capture ? _("Capture") : "", num); } /* set volume information */ if (track->num_channels > 0) { if ((flags & GST_MIXER_TRACK_OUTPUT)) snd_mixer_selem_get_playback_volume_range (element, &min, &max); else snd_mixer_selem_get_capture_volume_range (element, &min, &max); } track->min_volume = (gint) min; track->max_volume = (gint) max; for (i = 0; i < track->num_channels; i++) { long tmp = 0; if (flags & GST_MIXER_TRACK_OUTPUT) snd_mixer_selem_get_playback_volume (element, i, &tmp); else snd_mixer_selem_get_capture_volume (element, i, &tmp); alsa_track->volumes[i] = (gint) tmp; } gst_alsa_mixer_track_update (alsa_track); return track; }
/****************************************************************************** * setMixerVolume *****************************************************************************/ static Int setMixerVolume (Sound_Attrs *attrs) { Int status; snd_mixer_t *rcMixer; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; snd_mixer_selem_id_malloc (&sid); /* Open the mixer device */ status = snd_mixer_open (&rcMixer, 0); if ( status<0 ) { Dmai_err2 ("Failed to open mixer on %s (%s)\n", AUDIO_MIXER, snd_strerror (status)); return Dmai_EFAIL; } /* Attach mixer with sound card */ status = snd_mixer_attach (rcMixer,AUDIO_MIXER); if (status <0) { Dmai_err2 ("Failed to attach mixer on %s (%s)\n", AUDIO_MIXER, snd_strerror (status)); return Dmai_EFAIL; } /* Register mixer with selected elements */ status = snd_mixer_selem_register (rcMixer, NULL, NULL); if (status <0) { Dmai_err2 ("Failed to register mixer on %s (%s)\n", AUDIO_MIXER, snd_strerror (status)); return Dmai_EFAIL; } /* Load mixer */ status = snd_mixer_load (rcMixer); if (status <0) { Dmai_err2 ("Failed to load mixer on %s (%s)\n", AUDIO_MIXER, snd_strerror (status)); return Dmai_EFAIL; } for (elem = snd_mixer_first_elem (rcMixer); elem; elem=snd_mixer_elem_next(elem)) { snd_mixer_selem_get_id(elem,sid); if (!snd_mixer_selem_is_active(elem)) continue; if (attrs->mode == Sound_Mode_OUTPUT || attrs->mode == Sound_Mode_FULLDUPLEX) { if (snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT)) snd_mixer_selem_set_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT,attrs->leftGain); if (snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) snd_mixer_selem_set_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT,attrs->rightGain); } if (attrs->mode == Sound_Mode_INPUT || attrs->mode == Sound_Mode_FULLDUPLEX) { if (snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT)) snd_mixer_selem_set_capture_volume (elem, SND_MIXER_SCHN_FRONT_LEFT,attrs->leftGain); if (snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) snd_mixer_selem_set_capture_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT,attrs->rightGain); } } snd_mixer_selem_id_free (sid); snd_mixer_close (rcMixer); return Dmai_EOK; }