#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);
}
基於Alsa lib進行音量調節以及靜音操作
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.