当前位置: 首页 > news >正文

EasyPlayerPro windows播放器本地音频播放音量控制实现

背景描述

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

EasyPlayerPro播放器

实现流程

  • 调用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

技术支持

  • 邮件:support@easydarwin.org

  • QQ交流群:544917793

获取更多信息

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

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

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

Copyright © EasyDarwin Team 2012-2017

EasyDarwin

转载于:https://www.cnblogs.com/babosa/p/9217698.html

相关文章:

  • SQL Server索引内部结构:SQL Server索引的阶梯级别10
  • apache ant 修改java版本 方法之一
  • bzoj1911[Apio2010]特别行动队 斜率优化dp
  • 通俗理解webService及.net中的使用方法
  • PHP后门的eval类和system类 函数到底有哪些区别
  • mint-ui 填坑之路
  • 秒懂Vuejs、Angular、React原理和前端发展历史
  • Java定时器应用
  • 模型分离(选做)
  • 游戏全区全服和分区分服 QQ斗地主的设计
  • 【习题 7-7 UVA-12558】Egyptian Fractions (HARD version)
  • 仿腾讯固定导航栏
  • window进行缩放时左侧菜单高度随之变化
  • 如何将pdf文件的英文翻译成中文
  • mac用BootCamp装windows装完之后驱动问题
  • Android系统模拟器绘制实现概述
  • download使用浅析
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • nginx 负载服务器优化
  • nodejs:开发并发布一个nodejs包
  • 从零开始学习部署
  • 分享一份非常强势的Android面试题
  • 提醒我喝水chrome插件开发指南
  • 异常机制详解
  • 赢得Docker挑战最佳实践
  • mysql面试题分组并合并列
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • 带你开发类似Pokemon Go的AR游戏
  • 分布式关系型数据库服务 DRDS 支持显示的 Prepare 及逻辑库锁功能等多项能力 ...
  • 数据库巡检项
  • ​​​​​​​​​​​​​​Γ函数
  • ​决定德拉瓦州地区版图的关键历史事件
  • #QT(智能家居界面-界面切换)
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (09)Hive——CTE 公共表达式
  • (1) caustics\
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第2章第五节(日期和时间)
  • (八)五种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (翻译)terry crowley: 写给程序员
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (转)IOS中获取各种文件的目录路径的方法
  • (转)scrum常见工具列表
  • .NET 依赖注入和配置系统
  • .net(C#)中String.Format如何使用
  • .NET教程 - 字符串 编码 正则表达式(String Encoding Regular Express)
  • .NET运行机制
  • .xml 下拉列表_RecyclerView嵌套recyclerview实现二级下拉列表,包含自定义IOS对话框...
  • @Valid和@NotNull字段校验使用
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略
  • [Android]Android开发入门之HelloWorld