今日诗词欣赏:
晏殊 《蝶恋花》
槛菊愁烟兰泣露,罗幕轻寒,燕子双飞去。明月不谙离别苦,斜光到晓穿朱户。昨夜西风凋碧树,独上高楼,望尽天涯路。欲寄彩笺兼尺素,山长水阔知何处。
==========================================================================
主机操作系统:Centos 6.7
交叉编译器环境:arm-linux-gcc-4.5.4 (可通过命令/opt/buildroot-2012.08/arm920t/usr/bin/arm-linux-gcc -v查询)
开发板平台: fl2440
Linux内核版本: linux-3.0 .54
声卡:uda1341(音频编程接口:ALSA)
播放器:madplay
==========================================================================
之前我们http://blog.youkuaiyun.com/qicheng777/article/details/71082348 一文中实现了用按键控制madplay播放器,但是由于我们的开发板只有四个按键,所以并未添加控制音量的函数,所以,今天我们来编程实现用按键对播放器音量进行控制。不同于我们在开发板上用mixer直接设置音量,用程序控制可以实现在播放歌曲的时候随意更改当前音量大小。
一、设置音量函数:
给函数传一个值voice,这个值就是设置的当前增益。
void volume(int voice)
{
int MIX_FD; //定义文件描述符
int iLeft = voice; //左声道增益
int iRight = voice; //右声道增益
int iLevel;
iLevel = (iRight << 8) + iLeft; //
MIX_FD= open("/dev/mixer", O_WRONLY); //只写方式打开混音器
if (MIX_FD == -1) {
perror("Error:open /dev/mixer error");
exit(1);
}
/*设置混音通道增益*/
if (ioctl(MIX_FD, MIXER_WRITE(SOUND_MIXER_VOLUME), &iLevel) == -1) {
perror("Error:MIXER_WRITE ioctl failed");
exit(1);
}
/*读取混音通道增益*/
if (ioctl(MIX_FD, MIXER_READ(SOUND_MIXER_VOLUME), &iLevel) == -1) {
perror("Error:MIXER_WRITE ioctl failed");
exit(1);
}
close(MIX_FD);
}
这个函数很简单,主要是要知道如何通过ioctl来控制mixer混音器,之前也对混音器相关操作进行了总结,可参考:http://blog.youkuaiyun.com/qicheng777/article/details/71368101
二、修改主函数:
为了简便,我把之前关于播放器的其他操作(比如暂停,上一曲等等)以及控制音量的函数都封装在一个头文件(hand_play.h)中了,主函数可直接调用。
/*********************************************************************************
* Copyright: (C) 2017 qicheng
* All rights reserved.
*
* Filename: bbb.c
* Description: This file
*
* Version: 1.0.0(04/27/2017)
* Author: yangni <497049229@qq.com>
* ChangeLog: 1, Release initial version on "04/27/2017 07:49:28 PM"
*
********************************************************************************/
#include <stdlib.h>
#include "hand_play.h"
int main(void)
{
int buttons_fd;
int key_value;
struct song *head;
/*初始音量*/
static int vol=50; //这里定义了必须是一个静态变量
volume(vol);
/*打开设备文件*/
buttons_fd = open("/dev/button", 0);
if (buttons_fd < 0) {
perror("open device buttons");
exit(1);
}
/*创建播放列表*/
head = creat_song_list();
printf("===================================OPTION=======================================\n\n\n\n");
printf(" K1:START/PAUSE K2:STOP K3:NEXT K4:PRIOR\n\n\n\n");
printf("================================================================================\n");
/*共享内存:用于存放子进程ID,播放列表位置*/
if((shmid = shmget(IPC_PRIVATE,5,PERM))== -1)
exit(1);
p_addr = shmat(shmid,0,0);
memset(p_addr,'\0',1024);
while(1)
{
fd_set rds;
int ret;
FD_ZERO(&rds);
FD_SET(buttons_fd, &rds);
/*监听获取键值*/
ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);
if (ret < 0)
{
perror("select");
exit(1);
}
if (ret == 0)
printf("Timeout.\n");
else if (FD_ISSET(buttons_fd, &rds))
{
int ret = read(buttons_fd, &key_value, sizeof key_value);
if (ret != sizeof key_value)
{
if (errno != EAGAIN)
perror("read buttons\n");
continue;
}
else
{
//printf("buttons_value: %d\n", key_value+1);
/*首次播放,必须是按键1*/
if(first_key){
switch(key_value)
{
case KEY_1:
startplay(&pid,head);
first_key=0;
break;
case KEY_2:
case KEY_3:
case KEY_4:
printf("=======================PRESS K1 TO START PLAY===================\n");
break;
default:
printf("=======================PRESS K1 TO START PLAY===================\n");
break;
} //end switch
}//end if(first_key)
/*若不是首次播放,则根据不同键值处理*/
else if(!first_key){
switch(key_value)
{
case KEY_1:
//printf("play_flag:%d\n",play_flag);
if(play_flag)
my_pause(gradchild);
else
conti_play(gradchild);
break;
case KEY_2:
next(gradchild);
break;
case KEY_3:
/*减小音量*/
while(vol>0)
{
vol-=10; //每按键一次减10
volume(vol); //调用刚才我们写的函数设置音量
break;
}
break;
case KEY_4:
/*增大音量*/
while(vol<120)
{
vol+=10;
volume(vol); //调用函数
break;
}
break;
} //end switch
}//end if(!first_key)
}
}
}
close(buttons_fd);
return 0;
}
主函数中,定义音量的变量一定要是 静态变量,这样才能保证这个值不被重新初始化。然后在while循环中,一定要用break直接跳出函数。