背景描述

作为一个播放器, 除了能播放视频和声音外,音量控制是绝对不能缺少的功能; 本文在音视频播放的基础上,增加对音量的控制;

实现流程

  • 调用mixerGetDevCaps获取音频输出设备列表;
  • 打开指定的音频输出设备;
  • 获取指定音频输出设备的音频属性;
  • 获取和设置音量;
    DWORD GetVolume();
int SetVolume(DWORD vol);
int Init(DWORD ComponentType,int *min,int *max); int GetAudioOutputDeviceList(MIXER_DEVICE_INFO_T **devicelist, int *deviceNum);
int SetAudioDeviceId(int _deviceIdx);

代码实现

//获取音频输出设备列表
int CVolumeControl::GetAudioOutputDeviceList(MIXER_DEVICE_INFO_T **devicelist, int *deviceNum)
{
int idx = 0;
if (mDeviceNum < 1)
{
MIXERCAPS mxcaps;
UINT cMixerDevs = mixerGetNumDevs();
for (UINT iDevIndex = 0; iDevIndex < cMixerDevs && iDevIndex<MAX_MIXER_DEVICE_NUM; iDevIndex++)
{
mixerGetDevCaps(iDevIndex, &mxcaps, sizeof(mxcaps)); mixerDeviceList[iDevIndex].id = iDevIndex;
strcpy(mixerDeviceList[iDevIndex].name, mxcaps.szPname);
}
mDeviceNum = cMixerDevs;
} if (NULL != deviceNum) *deviceNum = mDeviceNum;
if (NULL != devicelist) *devicelist = &mixerDeviceList[0]; return 0;
} //获取音量
DWORD CVolumeControl::GetVolume()
{
int devIdx = mDeviceId; if (devIdx < 0) return -1; HMIXER hMixer;
MMRESULT mmhr;
mmhr = mixerOpen(&hMixer, devIdx, 0, 0, MIXER_OBJECTF_HMIXER|MIXER_GETLINEINFOF_DESTINATION);
if( mmhr != MMSYSERR_NOERROR )
{
_TRACE(TRACE_LOG_ERROR, "GetVolume::mixerOpen fail. %d\n", mmhr);
return 0;
} MIXERCAPS tmixercaps;
if( mixerGetDevCaps( devIdx, &tmixercaps, sizeof(MIXERCAPS)) != MMSYSERR_NOERROR )
{
mixerClose(hMixer);
return -1;
} bool ffind = false;
MIXERLINE mxline;
for(int i = 0; i < (int)tmixercaps.cDestinations; i++ )
{
ZeroMemory( &mxline, sizeof(MIXERLINE) );
mxline.cbStruct = sizeof(MIXERLINE);
mxline.dwDestination = i; mmhr = ::mixerGetLineInfo( (HMIXEROBJ)hMixer, &mxline, MIXER_OBJECTF_HMIXER);// | MIXER_GETLINEINFOF_COMPONENTTYPE );
if( mmhr != MMSYSERR_NOERROR ) {
continue;
}
else {
if( mxline.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_DIGITAL )
{
if( 0 != (MIXERLINE_LINEF_ACTIVE & mxline.fdwLine) )
{ ffind = true;
break; }
}
else if( mxline.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_MONITOR )
{
if( 0 != (MIXERLINE_LINEF_ACTIVE & mxline.fdwLine) )
{ ffind = true;
break; }
}
else if( mxline.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS )
{
if( 0 != (MIXERLINE_LINEF_ACTIVE & mxline.fdwLine) )
{ ffind = true;
break; }
}
}
} MIXERCONTROL mxcWaveoutMux;
memset(&mxcWaveoutMux, 0x00, sizeof(MIXERCONTROL));
_GetLineControls( hMixer, mxline, &mxcWaveoutMux, NULL, NULL ); MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED mxdu;
memset(&mxdu, 0x00, sizeof(MIXERCONTROLDETAILS_UNSIGNED)); mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.cMultipleItems = 0;
mxcd.cChannels = mxline.cChannels;
mxcd.dwControlID = mxcWaveoutMux.dwControlID;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxdu;
mmhr = mixerGetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_OBJECTF_HMIXER | MIXER_GETCONTROLDETAILSF_VALUE);
if( mmhr != MMSYSERR_NOERROR )
{
_TRACE(TRACE_LOG_ERROR, "GetVolume::mixerGetControlDetails fail. %d\n", mmhr);
}
mixerClose(hMixer); _TRACE(TRACE_LOG_DEBUG, "GetVolume: %d\n", mxdu.dwValue);
return mxdu.dwValue;
} //设置音量
int CVolumeControl::SetVolume(DWORD vol)
{
int devIdx = mDeviceId;
if (devIdx < 0) return -1; HMIXER hMixer;
MMRESULT mmhr;
mmhr = mixerOpen(&hMixer, 0, 0, 0, 0); if (mmhr!= MMSYSERR_NOERROR)
{
_TRACE(TRACE_LOG_ERROR, "mixerOpen fail. %d\n", mmhr);
return -1;
} MIXERCAPS tmixercaps;
if( mixerGetDevCaps( devIdx, &tmixercaps, sizeof(MIXERCAPS)) != MMSYSERR_NOERROR )
{
mixerClose(hMixer);
return -1;
} bool ffind = false;
MIXERLINE mxline;
for(int i = 0; i < (int)tmixercaps.cDestinations; i++ )
{
ZeroMemory( &mxline, sizeof(MIXERLINE) );
mxline.cbStruct = sizeof(MIXERLINE);
mxline.dwDestination = i; mmhr = ::mixerGetLineInfo( (HMIXEROBJ)hMixer, &mxline, MIXER_OBJECTF_HMIXER);// | MIXER_GETLINEINFOF_COMPONENTTYPE );
if( mmhr != MMSYSERR_NOERROR ) { continue;
}
else { //
if( mxline.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_DIGITAL )
{
if( 0 != (MIXERLINE_LINEF_ACTIVE & mxline.fdwLine) )
{ ffind = true;
break; }
}
else if( mxline.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_MONITOR )
{
if( 0 != (MIXERLINE_LINEF_ACTIVE & mxline.fdwLine) )
{ ffind = true;
break; }
}
else if( mxline.dwComponentType == MIXERLINE_COMPONENTTYPE_DST_SPEAKERS )
{
if( 0 != (MIXERLINE_LINEF_ACTIVE & mxline.fdwLine) )
{ ffind = true;
break; }
}
}
} MIXERCONTROL mxcWaveoutMux;
memset(&mxcWaveoutMux, 0x00, sizeof(MIXERCONTROL));
_GetLineControls( hMixer, mxline, &mxcWaveoutMux, NULL, NULL ); int ret = 0; MIXERCONTROLDETAILS mxcd;
MIXERCONTROLDETAILS_UNSIGNED mxdu;
memset(&mxdu, 0x00, sizeof(MIXERCONTROLDETAILS_UNSIGNED)); mxdu.dwValue = vol;
mxcd.cMultipleItems = 0;
mxcd.cChannels = mxline.cChannels;
mxcd.cbStruct = sizeof(MIXERCONTROLDETAILS);
mxcd.dwControlID = mxcWaveoutMux.dwControlID;
mxcd.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
mxcd.paDetails = &mxdu; mmhr = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd, MIXER_SETCONTROLDETAILSF_VALUE | MIXER_OBJECTF_HMIXER);
if (mmhr != MMSYSERR_NOERROR)
{
ret = -1;
} mixerClose(hMixer); return ret;
}

关于EasyPlayerPro播放器

EasyPlayerPro是一款全功能的流媒体播放器,支持RTSP、RTMP、HTTP、HLS、UDP、RTP、File等多种流媒体协议播放、支持本地文件播放,支持本地抓拍、本地录像、播放旋转、多屏播放、倍数播放等多种功能特性,核心基于ffmpeg,稳定、高效、可靠、可控,支持Windows、Android、iOS三个平台,目前在多家教育、安防、行业型公司,都得到的应用,广受好评!

EasyPlayerPro:https://github.com/EasyDSS/EasyPlayerPro

点击链接加入群【EasyPlayer & EasyPlayerPro】:544917793

技术支持

获取更多信息

EasyDarwin开源流媒体服务器:www.EasyDarwin.org

EasyDSS商用流媒体解决方案:www.EasyDSS.com

EasyNVR无插件直播方案:www.EasyNVR.com

Copyright © EasyDarwin Team 2012-2017

EasyPlayerPro windows播放器本地音频播放音量控制实现的更多相关文章

  1. iOS Dev (20) 用 AVAudioPlayer 播放一个本地音频文件

    iOS Dev (20) 用 AVAudioPlayer 播放一个本地音频文件 作者:CSDN 大锐哥 博客:http://blog.csdn.net/prevention 步骤 第一步:在 Proj ...

  2. iOS Dev (21) 用 AVPlayer 播放一个本地音频文件

    iOS Dev (21) 用 AVPlayer 播放一个本地音频文件 作者:CSDN 大锐哥 博客:http://blog.csdn.net/prevention 前言 这篇文章与上一篇极其相似,要注 ...

  3. H5播放器内置播放视频(兼容绝大多数安卓和ios)

    关于H5播放器内置播放视频,这个问题一直困扰我很长一段时间,qq以前提供白名单已经关闭,后来提供了同层属性的控制,或多或少也有点差强人意. 后来一次偶然发现一个非常简单的方法可以实现. 只需要给vid ...

  4. (1)H5实现音乐播放器【正在播放-歌词篇】

    近期闲来无事,就想着复习一下前端的东西,然后正好跟朋友搞了一个公共开放的音乐api接口,就想着写一个音乐播放器玩玩! 话不多说,直接上图,然后上代码 [播放器显示正在播放] 实现功能: 1:歌词随着歌 ...

  5. EasyPlayerPro windows播放器本地配置文件配置方法介绍

    需求背景 应EasyPlayerPro某客户需求,在EasyPlayerPro启动时,自动播放指定的url源, 不需要每次都去手动填写, 且实现自动播放,不需要手动的单击播放按钮: 为响应该需求,特增 ...

  6. EasyPlayerPro Windows播放器本地快照抓拍截图功能实现方法

    背景描述 作为一个播放器,截图功能必不可少; 下面主要记录一下截图功能的实现: 实现流程 将解码后的帧进行格式转换(目标格式为RGB24); 采用独立的线程进行截图处理; 截图可保存为BMP或JPG两 ...

  7. iOS中音频的录制与播放(本地音频文件的播放)

    iOS功能开发涉及到音频处理时,最常见的时进行录音,以及音频文件的播放.停止播放等的操作.在开发中还要避免同一个音频文件,或不同音频文件之间的处理,比如说正在播放A音频时,可以停止播放A音频,也可以播 ...

  8. android音乐播放器开发 SweetMusicPlayer 播放本地音乐

    上一篇写了载入歌曲列表,http://blog.csdn.net/huweigoodboy/article/details/39856411,如今来总结下播放本地音乐. 一,MediaPlayer 首 ...

  9. 使用Vitamio打造自己的Android万能播放器(2)—— 手势控制亮度、音量、缩放

    前言 本章继续完善播放相关播放器的核心功能,为后续扩展打好基础.   声明 欢迎转载,但请保留文章原始出处:)  博客园:http://www.cnblogs.com 农民伯伯: http://ove ...

随机推荐

  1. (9)JavaScript-DOM(文档对象模型)

    DOM是针对 HTML 和 XML 文档的一个 API ,描绘了一个层次化的节点树,允许开发人员添加.移除和修改页面的某一部分  一.节点层次 <html> <head> &l ...

  2. HDU 1060 Leftmost Digit【log10/求N^N的最高位数字是多少】

    Leftmost Digit Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  3. 在Linux 双机下自己手动实现浮动ip技术

    两台Linux服务器,一台为主机(IP:124.158.26.30)对外提供了一定的网络服务,另一台从机(IP:124.158.26.31)能提供相同的服务,但ip地址没有对外部公开客户端连接的都是1 ...

  4. Codeforces Round #324 (Div. 2) Marina and Vasya 乱搞推理

    原题链接:http://codeforces.com/contest/584/problem/C 题意: 定义$f(s1,s2)$为$s1,s2$不同的字母的个数.现在让你构造一个串$s3$,使得$f ...

  5. 寒假week1---二分查找(二分枚举)

    寒假week1---二分查找(二分枚举)1.适用条件:要查找(枚举)的集合有序 && 查找(枚举)的“条件”具有单调性2.什么是“条件”:example: 1.给定一个有序数组,从中查 ...

  6. 如何在SQLite中创建自增字段

      SQLite 简单的回答:一个声明为 INTEGER PRIMARY KEY 的字段将自动增加. 这里是详细的答案: 从 SQLite 的 2.3.4 版本开始,如果你将一个表中的一个字段声明为 ...

  7. DataSnap——利用TParams进行多表事务更新

    DataSnap——利用TParams进行多表事务更新 服务端: function TSVRDM.multUpdatesByPar(UpdateParam: TParams; out ErrMsg: ...

  8. iOS应用崩溃日志揭秘2

    这篇文章还可以在这里找到 英语 场景 4: 吃棒棒糖时闪退! 用户邮件说, “当rage master吃棒棒糖时应用就闪退…” 另一用户说, “我让rage master 吃棒棒糖,没几次应用就闪退了 ...

  9. 【windows】windows系统下,在任务管理器的进程选项卡中查看PID/任务管理器怎么查看PID

    PID,就是windows上的进程ID,是一个进程的唯一标识值. 那今天启动JDK跑起来一个项目之后,想要在任务管理器中查看这个JDK所在进程的PID但是看不到. 怎么解决? 1.我在任务管理器的服务 ...

  10. MyEclipse出错解决

    错误信息: Deployment failure on Tomcat  6.x. Could not copy all resources to C:\Tomcat 6.0\webapps\JavaP ...