#include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <alsa/asoundlib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/soundcard.h> #include "volume_interface.h" #define DEBUG(x,y...) //{printf("[ %s : %s : %d] ",__FILE__, __func__, __LINE__); printf(x,##y); printf("\n");} #define ERROR(x,y...) {printf("[ %s : %s : %d] ",__FILE__, __func__, __LINE__); printf(x,##y); printf("\n");} static char *alsa_mix_dev = "default"; static char *alsa_mix_headphone_ctrl = "Headphone"; static char *alsa_mix_digital_ctrl = "Digital"; static void volume_init(char *alsa_mix_ctrl, snd_mixer_t **alsa_mix_handle_p, snd_mixer_elem_t **alsa_mix_elem_p) { int alsa_mix_index = 0; snd_mixer_selem_id_t *alsa_mix_sid = NULL; snd_mixer_selem_id_alloca(&alsa_mix_sid); snd_mixer_selem_id_set_index(alsa_mix_sid, alsa_mix_index); snd_mixer_selem_id_set_name(alsa_mix_sid, alsa_mix_ctrl); if ((snd_mixer_open(alsa_mix_handle_p, 0)) < 0) DEBUG ("Failed to open mixer"); if ((snd_mixer_attach(*alsa_mix_handle_p, alsa_mix_dev)) < 0) DEBUG ("Failed to attach mixer"); if ((snd_mixer_selem_register(*alsa_mix_handle_p, NULL, NULL)) < 0) DEBUG ("Failed to register mixer element"); if (snd_mixer_load(*alsa_mix_handle_p) < 0) DEBUG ("Failed to load mixer element"); *alsa_mix_elem_p = snd_mixer_find_selem(*alsa_mix_handle_p, alsa_mix_sid); if (!*alsa_mix_elem_p) DEBUG ("Failed to find mixer element"); if (snd_mixer_selem_set_playback_volume_range (*alsa_mix_elem_p, 0, 100) < 0) DEBUG("Failed to set playback volume range"); } static void volume_uninit(snd_mixer_t *alsa_mix_handle) { if(alsa_mix_handle){ snd_mixer_close(alsa_mix_handle); } } int volume_get(void) { long ll, lr, vol; snd_mixer_t *alsa_mix_headphone_handle = NULL; snd_mixer_elem_t *alsa_mix_headphone_elem = NULL; //Headphone channel volume_init(alsa_mix_headphone_ctrl, &alsa_mix_headphone_handle, &alsa_mix_headphone_elem); //處理事件 snd_mixer_handle_events(alsa_mix_headphone_handle); //左聲道 snd_mixer_selem_get_playback_volume(alsa_mix_headphone_elem, SND_MIXER_SCHN_FRONT_LEFT, &ll); //右聲道 snd_mixer_selem_get_playback_volume(alsa_mix_headphone_elem, SND_MIXER_SCHN_FRONT_RIGHT, &lr); volume_uninit(alsa_mix_headphone_handle); /* //Digital channel snd_mixer_t *alsa_mix_digital_handle = NULL; snd_mixer_elem_t *alsa_mix_digital_elem = NULL; volume_init(alsa_mix_digital_ctrl, &alsa_mix_digital_handle, &alsa_mix_digital_elem); //處理事件 snd_mixer_handle_events(alsa_mix_digital_handle); //左聲道 snd_mixer_selem_get_playback_volume(alsa_mix_digital_elem, SND_MIXER_SCHN_FRONT_LEFT, &ll); //右聲道 snd_mixer_selem_get_playback_volume(alsa_mix_digital_elem, SND_MIXER_SCHN_FRONT_RIGHT, &lr); volume_uninit(alsa_mix_digital_handle); */ vol = (int)((ll + lr) >> 1); //DEBUG("volume_get vol %d, ll %ld, lr %ld", vol, ll, lr); return vol; } int volume_set(int vol, volume_domain domain) { snd_mixer_t *alsa_mix_headphone_handle = NULL; snd_mixer_t *alsa_mix_digital_handle = NULL; snd_mixer_elem_t *alsa_mix_headphone_elem = NULL; snd_mixer_elem_t *alsa_mix_digital_elem = NULL; if(vol > 100) vol = 100; if(vol < 0) vol = 0; if(vol == 0){ volume_mute(); }else{ volume_unmute(); } //Headphone channel volume_init(alsa_mix_headphone_ctrl, &alsa_mix_headphone_handle, &alsa_mix_headphone_elem); //左音量 snd_mixer_selem_set_playback_volume(alsa_mix_headphone_elem, SND_MIXER_SCHN_FRONT_LEFT, vol); //右音量 snd_mixer_selem_set_playback_volume(alsa_mix_headphone_elem, SND_MIXER_SCHN_FRONT_RIGHT, vol); volume_uninit(alsa_mix_headphone_handle); //Digital channel //Digital channel 修改量減半,防止音量太大失真 volume_init(alsa_mix_digital_ctrl, &alsa_mix_digital_handle, &alsa_mix_digital_elem); //左音量 snd_mixer_selem_set_playback_volume(alsa_mix_digital_elem, SND_MIXER_SCHN_FRONT_LEFT, vol / 2); //右音量 snd_mixer_selem_set_playback_volume(alsa_mix_digital_elem, SND_MIXER_SCHN_FRONT_RIGHT, vol / 2); volume_uninit(alsa_mix_digital_handle); return 0; } int set_volume_mute_value(int val) { int err = 0; char *card = alsa_mix_dev; snd_ctl_t *handle = NULL; snd_ctl_elem_value_t *ctl_elem_value; if (handle == NULL && (err = snd_ctl_open(&handle, card, 0)) < 0) { ERROR("Control %s open error: %s", card, snd_strerror(err)); return err; } if((err = snd_ctl_elem_value_malloc (&ctl_elem_value)) < 0){ ERROR("Control %s open error: %s", card, snd_strerror(err)); snd_ctl_close(handle); handle = NULL; return err; } snd_ctl_elem_value_set_numid (ctl_elem_value, 11); snd_ctl_elem_value_set_interface (ctl_elem_value, SND_CTL_ELEM_IFACE_MIXER); snd_ctl_elem_value_set_name (ctl_elem_value, "Digital Playback mute"); snd_ctl_elem_value_set_integer(ctl_elem_value, 0, val); if ((err = snd_ctl_elem_write(handle, ctl_elem_value)) < 0) { ERROR("Control %s element write error: %s", card, snd_strerror(err)); } snd_ctl_close(handle); handle = NULL; snd_ctl_elem_value_free (ctl_elem_value); return err; } int volume_mute() { return set_volume_mute_value(1); } int volume_unmute() { return set_volume_mute_value(0); }