示例#1
0
static int alsa_mixer_set_muted(snd_mixer_elem_t *elem, gboolean muted) {
  long val, min, max;

  /**if switch is available, get switch status directly*/
  if(snd_mixer_selem_has_playback_switch(elem)) {
    snd_mixer_selem_set_playback_switch(elem, 0, !muted);
    snd_mixer_selem_set_playback_switch(elem, 1, !muted);
    return 0;
  } else if(snd_mixer_selem_has_capture_switch(elem)) {
    snd_mixer_selem_set_capture_switch(elem, 0, !muted);
    snd_mixer_selem_set_capture_switch(elem, 1, !muted);
    return 0;
  }

  if(snd_mixer_selem_has_playback_volume(elem)) {
    snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
    val = muted ? min : max;
    snd_mixer_selem_set_playback_volume(elem, 0, val);
    snd_mixer_selem_set_playback_volume(elem, 1, val);
    return 0;
  } else if(snd_mixer_selem_has_capture_volume(elem)) {
    snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
    val = muted ? min : max;
    snd_mixer_selem_set_capture_volume(elem, 0, val);
    snd_mixer_selem_set_capture_volume(elem, 1, val);
    return 0;
  }

  return -1;
}
示例#2
0
static int get_current_input_source(px_mixer *Px)
{
   PxInfo *info = (PxInfo *)Px->info;
   snd_mixer_elem_t *elem;
   int sw;
   int i, j;

   if (!info->capture.handle) {
      return -1;
   }

   for (i = 0; i < info->capture.numselems; i++) {
      elem = info->capture.selems[i].elem;
      for (j = 0; j <= SND_MIXER_SCHN_LAST; j++) {
         if (snd_mixer_selem_has_capture_switch(elem)) {
            snd_mixer_selem_get_capture_switch(elem, j, &sw);
            if (sw) {
               return i;
            }
         }
      }
   }

   return -1; /* none */
}
示例#3
0
void
gam_app_update_visibility (GamApp *gam_app, GtkWidget *widget, 
        snd_mixer_elem_t *elem, gboolean saved_state){
    
    g_return_if_fail (GAM_IS_APP (gam_app));
    
    GamMixer *gam_mixer=gam_app_get_current_mixer(gam_app);
    
    int is_playback= snd_mixer_selem_has_playback_volume(elem)
                  || snd_mixer_selem_has_playback_switch(elem)
                  || (snd_mixer_selem_is_enumerated(elem) 
                    && snd_mixer_selem_is_enum_playback(elem));
    int is_capture = snd_mixer_selem_has_capture_volume(elem)
                  || snd_mixer_selem_has_capture_switch(elem)
                  || (snd_mixer_selem_is_enumerated(elem) 
                    && snd_mixer_selem_is_enum_capture(elem));
    //If nothing showed set show all
    if(!(gam_mixer_get_show_playback_elements(gam_mixer)||gam_mixer_get_show_capture_elements(gam_mixer)))
       gam_mixer_set_capture_playback(gam_app_get_current_mixer(gam_app), TRUE, TRUE);
    
    if(saved_state
       && ((is_playback && gam_mixer_get_show_playback_elements(gam_mixer))
       || (is_capture && gam_mixer_get_show_capture_elements(gam_mixer))))
      gtk_widget_show(widget);
    else        
      gtk_widget_hide(widget);
}
示例#4
0
static gboolean alsa_mixer_is_muted(snd_mixer_elem_t *elem, gboolean *need_reset) {
  int sw;
  long Rvol, Lvol, min, max;

  if(need_reset)
    *need_reset = FALSE;

  /**if switch is available, get switch status directly*/
  if(snd_mixer_selem_has_playback_switch(elem)) {
    snd_mixer_selem_get_playback_switch(elem, 0, &sw);
    return sw ? FALSE: TRUE;
  } else if(snd_mixer_selem_has_capture_switch(elem)) {
    snd_mixer_selem_get_capture_switch(elem, 0, &sw);
    return sw ? FALSE: TRUE;
  }

  if(snd_mixer_selem_has_playback_volume(elem)) {
    snd_mixer_selem_get_playback_volume(elem, 0, &Rvol);
    snd_mixer_selem_get_playback_volume(elem, 1, &Lvol);
    snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
    if(need_reset)
      *need_reset = !!(max - Rvol);
    return (Rvol + Lvol) ? FALSE: TRUE;
  } else if(snd_mixer_selem_has_capture_volume(elem)) {
    snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
    snd_mixer_selem_get_capture_volume(elem, 0, &Rvol);
    snd_mixer_selem_get_capture_volume(elem, 1, &Lvol);
    if(need_reset)
      *need_reset = !!(max - Rvol);
    return (Rvol + Lvol) ? FALSE: TRUE;
  }
}
示例#5
0
void
gam_toggle_set_state (GamToggle *gam_toggle, gboolean state)
{
    GamTogglePrivate *priv;
    const gboolean internal_state = gam_toggle_get_state (gam_toggle);
    int err;

    priv = GAM_TOGGLE_GET_PRIVATE (gam_toggle);

    if (state == internal_state) return;

    if (snd_mixer_selem_has_playback_switch (priv->elem)) {
        err = snd_mixer_selem_set_playback_switch_all (priv->elem, state);
    } else if (snd_mixer_selem_has_capture_switch (priv->elem)) {
        err = snd_mixer_selem_set_capture_switch_all (priv->elem, state);
    } else {
        g_warning ("%s (). No idea what to do for mixer element \"%s\"!",
                   __FUNCTION__, snd_mixer_selem_get_name (priv->elem));
        err = 0;
    }

    if (err)
        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (gam_toggle),
                                      internal_state);
}
示例#6
0
static void
gst_alsa_mixer_track_update_alsa_capabilities (GstAlsaMixerTrack * alsa_track)
{
  alsa_track->alsa_flags = 0;
  alsa_track->capture_group = -1;

  if (snd_mixer_selem_has_common_volume (alsa_track->element))
    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_VOLUME;

  if (snd_mixer_selem_has_playback_volume (alsa_track->element))
    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PVOLUME;

  if (snd_mixer_selem_has_capture_volume (alsa_track->element))
    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CVOLUME;

  if (snd_mixer_selem_has_common_switch (alsa_track->element))
    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_SWITCH;

  if (snd_mixer_selem_has_playback_switch (alsa_track->element))
    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PSWITCH;

  if (snd_mixer_selem_has_capture_switch (alsa_track->element)) {
    alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH;

    if (snd_mixer_selem_has_capture_switch_exclusive (alsa_track->element)) {
      alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH_EXCL;
      alsa_track->capture_group =
          snd_mixer_selem_get_capture_group (alsa_track->element);
    }
  }

  GST_LOG ("[%s] alsa_flags=0x%08x, capture_group=%d",
      snd_mixer_selem_get_name (alsa_track->element),
      alsa_track->alsa_flags, alsa_track->capture_group);
}
示例#7
0
static void set_mixer_element(snd_mixer_t *mixer,const char *name, int level,MixerAction action){
	const char *elemname;
	snd_mixer_elem_t *elem;
	long sndMixerPMin=0;
	long sndMixerPMax=0;
	long newvol=0;
	
	elem=snd_mixer_first_elem(mixer);
	
	while (elem!=NULL){
		elemname=snd_mixer_selem_get_name(elem);
		//ms_message("Found alsa mixer element %s.",elemname);
		if (strcmp(elemname,name)==0){
			switch(action){
				case CAPTURE:
				if (snd_mixer_selem_has_capture_volume(elem)){
					snd_mixer_selem_get_capture_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
					newvol=(((sndMixerPMax-sndMixerPMin)*level)/100)+sndMixerPMin;
					snd_mixer_selem_set_capture_volume_all(elem,newvol);
					//ms_message("Successfully set capture level for %s.",elemname);
					return;
				}
				break;
				case PLAYBACK:
				if (snd_mixer_selem_has_playback_volume(elem)){
					snd_mixer_selem_get_playback_volume_range(elem, &sndMixerPMin, &sndMixerPMax);
					newvol=(((sndMixerPMax-sndMixerPMin)*level)/100)+sndMixerPMin;
					snd_mixer_selem_set_playback_volume_all(elem,newvol);
					//ms_message("Successfully set playback level for %s.",elemname);
					return;
				}
				break;
				case CAPTURE_SWITCH:
				if (snd_mixer_selem_has_capture_switch(elem)){
					snd_mixer_selem_set_capture_switch_all(elem,level);
					//ms_message("Successfully set capture switch for %s.",elemname);
				}
				break;
				case PLAYBACK_SWITCH:
				if (snd_mixer_selem_has_playback_switch(elem)){
					snd_mixer_selem_set_playback_switch_all(elem,level);
					//ms_message("Successfully set capture switch for %s.",elemname);
				}
				break;

			}
		}
		elem=snd_mixer_elem_next(elem);
	}

	return ;
}
示例#8
0
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;
}
示例#9
0
/*
 * Class:     org_tritonus_lowlevel_alsa_AlsaMixerElement
 * Method:    hasCaptureSwitch
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL
Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasCaptureSwitch
(JNIEnv* env, jobject obj)
{
    snd_mixer_elem_t*	handle;
    int			nReturn;

    if (debug_flag) {
        (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasCaptureSwitch(): begin\n");
    }
    handle = getHandle(env, obj);
    nReturn = snd_mixer_selem_has_capture_switch(handle);
    if (debug_flag) {
        (void) fprintf(debug_file, "Java_org_tritonus_lowlevel_alsa_AlsaMixerElement_hasCaptureSwitch(): end\n");
    }
    return (jboolean) nReturn;
}
示例#10
0
bool AlsaMixer::GetChannelSwitch( const char* channel, bool* on )
{
	bool success = false;
	snd_mixer_elem_t *elem;
	snd_mixer_selem_id_t *sid;
	snd_mixer_selem_id_alloca(&sid);

	snd_mixer_selem_id_set_index( sid, 0);
	snd_mixer_selem_id_set_name( sid, channel);
	elem = snd_mixer_find_selem(_handle, sid);
	if (!elem) {
		LOG( Logger::LOG_ERROR, "Unable to find simple control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
		goto end;
	}

	if( snd_mixer_selem_has_playback_switch(elem) )
	{
		for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
			int value;
			if (snd_mixer_selem_get_playback_switch(elem, (snd_mixer_selem_channel_id_t)chn, &value) >= 0)
			{
				*on = value != 0; 
				success = true;
				break;
			}
		}
	}else if( snd_mixer_selem_has_capture_switch(elem) )
	{
		for (int chn = 0; chn <= SND_MIXER_SCHN_LAST; chn++) {
			int value;
			if (snd_mixer_selem_get_capture_switch(elem, (snd_mixer_selem_channel_id_t)chn, &value ) >= 0)
			{
				*on = value != 0; 
				success = true;
				break;
			}
		}
	}
	if( !success )
	{
		LOG( Logger::LOG_ERROR, "Error getting control '%s',%i\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
	}
 end:
	return success;
}
示例#11
0
gboolean
gam_toggle_get_state (GamToggle *gam_toggle)
{
    GamTogglePrivate *priv;
    gint value = 0;

    priv = GAM_TOGGLE_GET_PRIVATE (gam_toggle);

    if (snd_mixer_selem_has_playback_switch (priv->elem)) {
        snd_mixer_selem_get_playback_switch (priv->elem, 0, &value);
    } else if (snd_mixer_selem_has_capture_switch (priv->elem)) {
        snd_mixer_selem_get_capture_switch (priv->elem, 0, &value);
    } else {
        g_warning ("%s (). No idea what to do for mixer element \"%s\"!",
                   __FUNCTION__, snd_mixer_selem_get_name (priv->elem));
    }

    return value;
}
示例#12
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);
}
示例#13
0
static void set_current_input_source(px_mixer *Px, int i)
{
   PxInfo *info = (PxInfo *)Px->info;
   snd_mixer_elem_t *elem;
   int j;

   if (!info->capture.handle) {
      return;
   }

   if (i < 0 || i >= info->capture.numselems) {
      return;
   }

   elem = info->capture.selems[i].elem;
   for (j = 0; j <= SND_MIXER_SCHN_LAST; j++) {
      if (snd_mixer_selem_has_capture_switch(elem)) {
         snd_mixer_selem_set_capture_switch(elem, j, TRUE);
      }
   }

   return;
}
status_t ALSAMixer::setCaptureMuteState(uint32_t device, bool state)
{
    for (int j = 0; mixerProp[j][SND_PCM_STREAM_CAPTURE].device; j++)
        if (mixerProp[j][SND_PCM_STREAM_CAPTURE].device & device) {

            mixer_info_t *info = mixerProp[j][SND_PCM_STREAM_CAPTURE].mInfo;
            if (!info || !info->elem) return INVALID_OPERATION;

            if (snd_mixer_selem_has_capture_switch (info->elem)) {

                int err = snd_mixer_selem_set_capture_switch_all (info->elem, static_cast<int>(!state));
                if (err < 0) {
                    ALOGE("Unable to %s capture mixer switch %s",
                        state ? "enable" : "disable", info->name);
                    return INVALID_OPERATION;
                }
            }

            info->mute = state;
        }

    return NO_ERROR;
}
示例#15
0
static int alsa_mixer_init(alsa_mixer_t *mixer, char *card) {
  snd_mixer_selem_id_t *sid;
  snd_mixer_elem_t *elem;
  snd_mixer_selem_id_alloca(&sid);
  int err;

  if ((err = snd_mixer_open(&mixer->handle, 0)) < 0) {
    DEBUG("Mixer %s open error: %s", card, snd_strerror(err));
    mixer->handle = NULL;
    return err;
  }

  if ((err = snd_mixer_attach(mixer->handle, card)) < 0) {
    DEBUG("Mixer %s local error: %s\n", card, snd_strerror(err));
    snd_mixer_close(mixer->handle);
    mixer->handle = NULL;
    return err;
  }

  if ((err = snd_mixer_selem_register(mixer->handle, NULL, NULL)) < 0) {
    DEBUG("Mixer register error: %s", snd_strerror(err));
    snd_mixer_close(mixer->handle);
    return err;
  }

  snd_mixer_set_callback(mixer->handle, on_mixer_event);
  err = snd_mixer_load(mixer->handle);
  if (err < 0) {
    DEBUG("Mixer %s load error: %s", card, snd_strerror(err));
    snd_mixer_close(mixer->handle);
    return err;
  }

  for (elem = snd_mixer_first_elem(mixer->handle); elem; elem = snd_mixer_elem_next(elem)) {
    const char *name = NULL;
    snd_mixer_selem_get_id(elem, sid);
    if (!snd_mixer_selem_is_active(elem))
      continue;

    name = snd_mixer_selem_id_get_name(sid);
    if(snd_mixer_selem_has_playback_volume(elem)) {
      if(strcmp(name, "Master") == 0)
        mixer->master = elem;
      else if(strcmp(name, "PCM") == 0)
        mixer->pcm = elem;
    } else if(snd_mixer_selem_has_capture_volume(elem) || snd_mixer_selem_has_capture_switch(elem)) {
      DEBUG("capture elem name = %s\n", name);
      /**make sure have one capture source if capture is available*/
      if(NULL == mixer->mic) {
        mixer->mic = elem;
      }
      /**if have Microphone, replace it*/
      if(strcmp(name, "Microphone") == 0)
        mixer->mic = elem;
      if(strcmp(name, "Capture") == 0)
        mixer->mic = elem;
    }
  }

  DEBUG("master = %x, pcm = %x, microphone = %x\n", mixer->master, mixer->pcm, mixer->mic);
  return 0;
}
示例#16
0
文件: lamixer.c 项目: metsger/lamixer
MixerElem *lamixer_volelem_new(snd_mixer_elem_t *elem)
{
	MixerElem *mixer_elem;
	guint voltype=0, elemidx=0, mono;
	long minrange=0,maxrange=0,rangevalue_left=0,rangevalue_right=0;
	const char* selem_name = NULL;
	char elem_name[64];
	
	mixer_elem = g_malloc(sizeof(MixerElem));
	mixer_elem->elem = elem;
	mixer_elem->playback = NULL;
	mixer_elem->capture = NULL;
	mixer_elem->pswitch = NULL;
	mixer_elem->cswitch = NULL;
	mixer_elem->penum = NULL;
	mixer_elem->cenum = NULL;
	
	elemidx = snd_mixer_selem_get_index(elem);
	selem_name = snd_mixer_selem_id_get_name(sid);
	strcpy(elem_name, selem_name);
	if(elemidx > 0) {
		sprintf(elem_name,"%s %i",elem_name, elemidx);
	}
	
	if (!snd_mixer_selem_is_enumerated(elem)) {
		if (snd_mixer_selem_has_playback_volume(elem)) {
			voltype = 1;
			snd_mixer_selem_get_playback_volume_range (elem, &minrange, &maxrange);
			mono = snd_mixer_selem_is_playback_mono(elem);
			snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &rangevalue_left);
			
			if(!mono)
				snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, &rangevalue_right);
			
			mixer_elem->playback = lamixer_volbox_new(elem_name,mono, \
			                                                (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_playback_switch_joined(elem)), minrange, maxrange, elem, voltype);
		}
		else if (snd_mixer_selem_has_playback_switch(elem)) {
			voltype = 1;
			mixer_elem->pswitch = lamixer_switchbox_add(elem_name, elem, voltype);
		}
		
		if (snd_mixer_selem_has_capture_volume(elem)) {
			voltype = 2;
			snd_mixer_selem_get_capture_volume_range (elem, &minrange, &maxrange);
			mono = snd_mixer_selem_is_capture_mono(elem);
			snd_mixer_selem_get_capture_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &rangevalue_left);
			
			if(!mono)
				snd_mixer_selem_get_capture_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, &rangevalue_right);
			
			mixer_elem->capture = lamixer_volbox_new(elem_name,mono, \
									(snd_mixer_selem_has_capture_switch(elem) || snd_mixer_selem_has_capture_switch_joined(elem)), minrange, maxrange, elem, voltype);
		}
		else if (snd_mixer_selem_has_capture_switch(elem)) {
			voltype = 2;
			mixer_elem->cswitch = lamixer_switchbox_add(elem_name, elem, voltype);
		}
	}
	else {
		if (snd_mixer_selem_is_enum_playback(elem)) {
			voltype = 1;
			mixer_elem->penum = lamixer_enumbox_add(elem_name, elem, voltype);
		}
		else if (snd_mixer_selem_is_enum_capture(elem)) {
			voltype = 2;
			mixer_elem->cenum = lamixer_enumbox_add(elem_name, elem, voltype);
		}
	}
		
	return mixer_elem;
}
示例#17
0
static void
gst_alsa_mixer_ensure_track_list (GstAlsaMixer * mixer)
{
  gint i, count;
  snd_mixer_elem_t *element, *master;
  GList *item;

  g_return_if_fail (mixer->handle != NULL);

  if (mixer->tracklist)
    return;

  g_static_rec_mutex_lock (mixer->rec_mutex);

  master = gst_alsa_mixer_find_master_mixer (mixer, mixer->handle);

  count = snd_mixer_get_count (mixer->handle);
  element = snd_mixer_first_elem (mixer->handle);

  /* build track list
   *
   * Some ALSA tracks may have playback and capture capabilities.
   * Here we model them as two separate GStreamer tracks.
   */

  for (i = 0; i < count; i++) {
    GstMixerTrack *play_track = NULL;
    GstMixerTrack *cap_track = NULL;
    const gchar *name;
    GList *item;
    gint samename = 0;

    name = snd_mixer_selem_get_name (element);

    /* prevent dup names */
    for (item = mixer->tracklist; item != NULL; item = item->next) {
      snd_mixer_elem_t *temp;

      if (GST_IS_ALSA_MIXER_OPTIONS (item->data))
        temp = GST_ALSA_MIXER_OPTIONS (item->data)->element;
      else
        temp = GST_ALSA_MIXER_TRACK (item->data)->element;

      if (strcmp (name, snd_mixer_selem_get_name (temp)) == 0)
        samename++;
    }

    GST_LOG ("[%s] probing element #%u, mixer->dir=%u", name, i, mixer->dir);

    if (mixer->dir & GST_ALSA_MIXER_PLAYBACK) {
      gboolean has_playback_switch, has_playback_volume;

      has_playback_switch = snd_mixer_selem_has_playback_switch (element);
      has_playback_volume = snd_mixer_selem_has_playback_volume (element);

      GST_LOG ("[%s] PLAYBACK: has_playback_volume=%d, has_playback_switch=%d"
          "%s", name, has_playback_volume, has_playback_switch,
          (element == master) ? " MASTER" : "");

      if (has_playback_volume) {
        gint flags = GST_MIXER_TRACK_OUTPUT;

        if (element == master)
          flags |= GST_MIXER_TRACK_MASTER;

        play_track = gst_alsa_mixer_track_new (element, samename, i,
            flags, FALSE, NULL, FALSE);

      } else if (has_playback_switch) {
        /* simple mute switch */
        play_track = gst_alsa_mixer_track_new (element, samename, i,
            GST_MIXER_TRACK_OUTPUT, TRUE, NULL, FALSE);
      }

      if (snd_mixer_selem_is_enumerated (element)) {
        GstMixerOptions *opts = gst_alsa_mixer_options_new (element, i);

        GST_LOG ("[%s] is enumerated (%d)", name, i);
        mixer->tracklist = g_list_append (mixer->tracklist, opts);
      }
    }

    if (mixer->dir & GST_ALSA_MIXER_CAPTURE) {
      gboolean has_capture_switch, has_common_switch;
      gboolean has_capture_volume, has_common_volume;

      has_capture_switch = snd_mixer_selem_has_capture_switch (element);
      has_common_switch = snd_mixer_selem_has_common_switch (element);
      has_capture_volume = snd_mixer_selem_has_capture_volume (element);
      has_common_volume = snd_mixer_selem_has_common_volume (element);

      GST_LOG ("[%s] CAPTURE: has_capture_volume=%d, has_common_volume=%d, "
          "has_capture_switch=%d, has_common_switch=%d, play_track=%p", name,
          has_capture_volume, has_common_volume, has_capture_switch,
          has_common_switch, play_track);

      if (has_capture_volume && !(play_track && has_common_volume)) {
        cap_track = gst_alsa_mixer_track_new (element, samename, i,
            GST_MIXER_TRACK_INPUT, FALSE, NULL, play_track != NULL);
      } else if (has_capture_switch && !(play_track && has_common_switch)) {
        cap_track = gst_alsa_mixer_track_new (element, samename, i,
            GST_MIXER_TRACK_INPUT, TRUE, NULL, play_track != NULL);
      }
    }


    if (play_track && cap_track) {
      GST_ALSA_MIXER_TRACK (play_track)->shared_mute =
          GST_ALSA_MIXER_TRACK (cap_track);
      GST_ALSA_MIXER_TRACK (cap_track)->shared_mute =
          GST_ALSA_MIXER_TRACK (play_track);
    }

    if (play_track)
      mixer->tracklist = g_list_append (mixer->tracklist, play_track);

    if (cap_track)
      mixer->tracklist = g_list_append (mixer->tracklist, cap_track);

    element = snd_mixer_elem_next (element);
  }

  for (item = mixer->tracklist; item != NULL; item = item->next) {
    snd_mixer_elem_t *temp;

    if (GST_IS_ALSA_MIXER_OPTIONS (item->data))
      temp = GST_ALSA_MIXER_OPTIONS (item->data)->element;
    else
      temp = GST_ALSA_MIXER_TRACK (item->data)->element;

    snd_mixer_elem_set_callback (temp, gst_alsa_mixer_elem_handle_callback);
    snd_mixer_elem_set_callback_private (temp, mixer);
  }

  g_static_rec_mutex_unlock (mixer->rec_mutex);
}
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");
}
示例#19
0
文件: mixer.c 项目: pzanoni/tray
static int _has_switch(snd_mixer_elem_t *elem, int playback)
{
	return playback ?
		snd_mixer_selem_has_playback_switch(elem) :
		snd_mixer_selem_has_capture_switch(elem);
}
示例#20
0
static int open_mixer(PxDev *dev, int card, int playback)
{
   snd_mixer_elem_t *elem;
   char name[256];
   int err;
   int i;

   sprintf(name, "hw:%d", card);

   dev->card = card;
   dev->handle = NULL;

   do {
      err = snd_mixer_open(&dev->handle, 0);
      if (err < 0) {
         break;
      }

      err = snd_mixer_attach(dev->handle, name);
      if (err < 0) {
         break;
      }

      err = snd_mixer_selem_register(dev->handle, NULL, NULL);
      if (err < 0) {
         break;
      }

      err = snd_mixer_load(dev->handle);
      if (err < 0) {
         break;
      }

      for (elem = snd_mixer_first_elem(dev->handle);
           elem != NULL;
           elem = snd_mixer_elem_next(elem))
      {
         if (!playback) {
            if (!snd_mixer_selem_has_capture_volume(elem) &&
                !snd_mixer_selem_has_capture_switch(elem) &&
                !snd_mixer_selem_has_common_volume(elem)) {
               continue;
            }
         }
         else {
            if (!snd_mixer_selem_has_playback_volume(elem) &&
                !snd_mixer_selem_has_playback_switch(elem) &&
                !snd_mixer_selem_has_common_volume(elem)) {
               continue;
            }
         }
         dev->numselems++;
      }

      dev->selems = calloc(dev->numselems, sizeof(PxSelem));
      if (dev->selems == NULL) {
         break;
      }

      i = 0;
      for (elem = snd_mixer_first_elem(dev->handle);
           elem != NULL;
           elem = snd_mixer_elem_next(elem))
      {
         if (!playback) {
            if (!snd_mixer_selem_has_capture_volume(elem) &&
                !snd_mixer_selem_has_capture_switch(elem) &&
                !snd_mixer_selem_has_common_volume(elem)) {
               continue;
            }
         }
         else {
            if (!snd_mixer_selem_has_playback_volume(elem) &&
                !snd_mixer_selem_has_playback_switch(elem) &&
                !snd_mixer_selem_has_common_volume(elem)) {
               continue;
            }
         }
               
         if (snd_mixer_selem_id_malloc(&dev->selems[i].sid) < 0) {
            break;
         }

         snd_mixer_selem_get_id(elem, dev->selems[i].sid);
         dev->selems[i].elem = elem;

         snprintf(name,
                  sizeof(name),
                  "%s:%d",
                  snd_mixer_selem_id_get_name(dev->selems[i].sid),
                  snd_mixer_selem_id_get_index(dev->selems[i].sid));

         dev->selems[i].name = strdup(name);
         if (!dev->selems[i].name) {
            break;
         }
         i++;
      }

      if (i == dev->numselems) {
         return TRUE;
      }

   } while (FALSE);

   if (dev->selems) {
      for (i = 0; i < dev->numselems; i++) {
         if (dev->selems[i].sid) {
            snd_mixer_selem_id_free(dev->selems[i].sid);
         }
         if (dev->selems[i].name) {
            free(dev->selems[i].name);
         }
      }
      free(dev->selems);
      dev->selems = NULL;
   }

   if (dev->handle) {
      snd_mixer_close(dev->handle);
      dev->handle = NULL;
   }

   return FALSE;
}