?? cpi_player.c
字號:
#include "stdafx.h"
#include "globals.h"
#include "CPI_Player.h"
#include "CPI_Player_Messages.h"
CPI_Player__SetInternalVolume(CPs_PlayEngine* pPlayEngine, const int iNewVolume);
CP_HPLAYER CPI_Player__Create(HWND hWndMain)
{
CPs_PlayEngine* pNewPlayEngine;
// 線程控制對象
pNewPlayEngine = (CPs_PlayEngine*)malloc(sizeof(CPs_PlayEngine));
pNewPlayEngine->m_hWndNotify = hWndMain;
// 創(chuàng)建事件,當(dāng)線程準備好輸入時,事件將被通知
pNewPlayEngine->m_hEvtThreadReady = CreateEvent(NULL, FALSE, FALSE, NULL);
// 創(chuàng)建線程
pNewPlayEngine->m_hThread = CreateThread(NULL, 0, CPI_Player__EngineEP, pNewPlayEngine, 0, &(pNewPlayEngine->m_dwThreadID) );
CP_ASSERT(pNewPlayEngine->m_hThread);
// 等待引擎就緒
WaitForSingleObject(pNewPlayEngine->m_hEvtThreadReady, INFINITE);
CloseHandle(pNewPlayEngine->m_hEvtThreadReady);
pNewPlayEngine->m_hEvtThreadReady = NULL;
pNewPlayEngine->m_hVolumeMixer = NULL;
CPI_Player__ReopenMixer((CP_HPLAYER)pNewPlayEngine);
return (CP_HPLAYER)pNewPlayEngine;
}
//
//
//
void CPI_Player__Destroy(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 請求線程關(guān)閉
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_STOP, 0, 0);
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_QUIT, 0, 0);
// 關(guān)閉音量混合器
if(pPlayEngine->m_hVolumeMixer)
mixerClose(pPlayEngine->m_hVolumeMixer);
// 等待關(guān)閉實際上發(fā)生
WaitForSingleObject(pPlayEngine->m_hThread, INFINITE);
// 清空
CloseHandle(pPlayEngine->m_hThread);
free(pPlayEngine);
}
//
//
//
void CPI_Player__ReopenMixer(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
WAVEFORMATEX waveformatex;
HWAVEOUT hWaveOut;
CP_CHECKOBJECT(pPlayEngine);
// 關(guān)閉音量混合器
if(pPlayEngine->m_hVolumeMixer)
{
mixerClose(pPlayEngine->m_hVolumeMixer);
pPlayEngine->m_hVolumeMixer = NULL;
}
if(globals.m_enMixerMode == mmMasterVolume || globals.m_enMixerMode == mmWaveVolume)
{
// 通過打開波形輸出流并由此打開混聲器,獲得混聲器ID
waveformatex.wFormatTag = WAVE_FORMAT_PCM;
waveformatex.nChannels = 2;
waveformatex.nSamplesPerSec = 44100;
waveformatex.wBitsPerSample = 16;
waveformatex.nBlockAlign = (waveformatex.nChannels * waveformatex.wBitsPerSample)>>3;
waveformatex.nAvgBytesPerSec = waveformatex.nSamplesPerSec * waveformatex.nBlockAlign;
waveformatex.cbSize = 0;
waveOutOpen( &hWaveOut,
WAVE_MAPPER,
&waveformatex,
0,
0, CALLBACK_NULL);
// 為音量創(chuàng)建一個混聲器(mixer)控制 (如果可以)
if(mixerOpen(&pPlayEngine->m_hVolumeMixer, (UINT)hWaveOut, (DWORD)pPlayEngine->m_hWndNotify, 0, CALLBACK_WINDOW | MIXER_OBJECTF_HWAVEOUT) == MMSYSERR_NOERROR)
{
MIXERCAPS mixercaps;
DWORD dwLineID;
DWORD dwNumControls;
MIXERLINECONTROLS linecontrols;
MIXERCONTROL mixercontrol;
// 為第一個波形輸出設(shè)備的揚聲器獲得目的文件的
mixerGetDevCaps((UINT)pPlayEngine->m_hVolumeMixer, &mixercaps, sizeof(mixercaps));
{
MIXERLINE mixerline;
memset(&mixerline, 0, sizeof(mixerline));
mixerline.cbStruct = sizeof(mixerline);
if(globals.m_enMixerMode == mmMasterVolume)
{
mixerline.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
mixerGetLineInfo((HMIXEROBJ)pPlayEngine->m_hVolumeMixer,
&mixerline,
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE);
}
else
{
mixerline.Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
mixerline.Target.wMid = mixercaps.wMid;
mixerline.Target.wPid = mixercaps.wPid;
mixerline.Target.vDriverVersion = mixercaps.vDriverVersion;
strncpy(mixerline.Target.szPname, mixercaps.szPname, sizeof(mixerline.Target.szPname));
mixerGetLineInfo((HMIXEROBJ)pPlayEngine->m_hVolumeMixer,
&mixerline,
MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_TARGETTYPE);
}
dwLineID = mixerline.dwLineID;
dwNumControls = mixerline.cControls;
}
// 獲得音量控制器的 controlID
memset(&linecontrols, 0, sizeof(linecontrols));
linecontrols.cbStruct = sizeof(linecontrols);
linecontrols.dwLineID = dwLineID;
linecontrols.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
linecontrols.cControls = 1;
linecontrols.cbmxctrl = sizeof(MIXERCONTROL);
linecontrols.pamxctrl = &mixercontrol;
memset(&mixercontrol, 0, sizeof(mixercontrol));
mixercontrol.cbStruct = sizeof(mixercontrol);
mixerGetLineControls((HMIXEROBJ)pPlayEngine->m_hVolumeMixer,
&linecontrols,
MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE);
pPlayEngine->m_dwMixerControlID = mixercontrol.dwControlID;
CPI_Player__SetInternalVolume(pPlayEngine, 100);
}
else
{
CP_TRACE0("Failed to open mixer");
pPlayEngine->m_hVolumeMixer = NULL;
}
waveOutClose(hWaveOut);
}
else
{
CPI_Player__SetInternalVolume(pPlayEngine, globals.m_iVolume);
}
}
//
//
//
void CPI_Player__OpenFile(CP_HPLAYER hPlayer, const char* pcFilename)
{
char* pcStringCopy;
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 對流數(shù)據(jù)作備份
STR_AllocSetString(&pcStringCopy, pcFilename, FALSE);
// 發(fā)送消息 (被調(diào)用者將釋放串)
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_OPENFILE, (WPARAM)pcStringCopy, 0);
}
//
//
//
void CPI_Player__Seek(CP_HPLAYER hPlayer, const int iSeekPercent_Numerator, const int iSeekPercent_Denominator)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SEEK, (WPARAM)iSeekPercent_Numerator, (LPARAM)iSeekPercent_Denominator);
}
//
//
//
void CPI_Player__Play(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_PLAY, 0, 0);
}
//
//
//
void CPI_Player__Stop(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_STOP, 0, 0);
}
//
//
//
void CPI_Player__Pause(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_PAUSE, 0, 0);
}
//
//
//
void CPI_Player__BlockMessagesUntilEndOfStream(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_BLOCKMSGUNTILENDOFSTREAM, 0, 0);
}
//
//
//
void CPI_Player__SetVolume(CP_HPLAYER hPlayer, const int iNewVolume)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 通過混聲器設(shè)置音量
if(pPlayEngine->m_hVolumeMixer)
{
MIXERCONTROLDETAILS_UNSIGNED VolumeLevel;
MIXERCONTROLDETAILS details;
details.cbStruct = sizeof(details);
details.dwControlID = pPlayEngine->m_dwMixerControlID;
details.cChannels = 1;
details.hwndOwner = NULL;
details.cMultipleItems = 0;
details.cbDetails = sizeof(VolumeLevel);
details.paDetails = &VolumeLevel;
VolumeLevel.dwValue = iNewVolume * 0x28F;
mixerSetControlDetails((HMIXEROBJ)pPlayEngine->m_hVolumeMixer, &details, MIXER_OBJECTF_HMIXER);
}
else
CPI_Player__SetInternalVolume(pPlayEngine, globals.m_iVolume);
}
//
//
//
int CPI_Player__GetVolume(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 通過混聲器得到音量
if(pPlayEngine->m_hVolumeMixer)
{
MIXERCONTROLDETAILS_UNSIGNED VolumeLevel;
MIXERCONTROLDETAILS details;
details.cbStruct = sizeof(details);
details.dwControlID = pPlayEngine->m_dwMixerControlID;
details.cChannels = 1;
details.hwndOwner = NULL;
details.cMultipleItems = 0;
details.cbDetails = sizeof(VolumeLevel);
details.paDetails = &VolumeLevel;
VolumeLevel.dwValue = 0;
mixerGetControlDetails((HMIXEROBJ)pPlayEngine->m_hVolumeMixer, &details, MIXER_OBJECTF_HMIXER);
return VolumeLevel.dwValue / 0x28F;
}
else
return globals.m_iVolume;
}
//
//
//
void CPI_Player__SetEQ(CP_HPLAYER hPlayer, const BOOL bEnabled, const int cBands[9])
{
int iEQBandIDX;
CPs_EQSettings* pNewEQSettings;
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 設(shè)置params
pNewEQSettings = (CPs_EQSettings*)malloc(sizeof(*pNewEQSettings));
pNewEQSettings->m_bEnabled = bEnabled;
// 設(shè)置帶 - 由于一些原因,UI 基于1 !!!
for(iEQBandIDX = 0; iEQBandIDX < 8; iEQBandIDX++)
pNewEQSettings->m_aryBands[iEQBandIDX] = (char)cBands[iEQBandIDX+1];
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SETEQSETTINGS, (WPARAM)pNewEQSettings, 0);
}
//
//
//
void CPI_Player__EnumOutputDevices(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_ENUMOUTPUTDEVICES, 0, 0);
}
//
//
//
void CPI_Player__SendSyncCookie(CP_HPLAYER hPlayer, const int iCookie)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SENDSYNCCOOKIE, (WPARAM)iCookie, 0);
}
//
//
//
void CPI_Player__SetPositionRange(CP_HPLAYER hPlayer, const int iRange)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SETPROGRESSTRACKLENGTH, (WPARAM)iRange, 0);
}
//
//
//
void CPI_Player__AssociateFileExtensions(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_ASSOCIATEFILEEXTENSIONS, 0, 0);
}
//
//
//
BOOL CPI_Player__HandleNotifyMessages(CP_HPLAYER hPlayer, UINT uiMessage, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
{
// 如果不是為此目的的消息,則忽略之
if( (uiMessage < CPNM_first || uiMessage > CPNM_last)
&& uiMessage != MM_MIXM_CONTROL_CHANGE)
{
return FALSE;
}
// 解碼消息
switch(uiMessage)
{
case CPNM_PLAYERSTATE:
{
CPe_PlayerState enNewState = (CPe_PlayerState)wParam;
CPI_Player_cb_OnPlayerState(hPlayer, enNewState);
}
break;
case CPNM_FILEINFO:
{
CPs_FileInfo* pFileInfo = (CPs_FileInfo*)wParam;
CPI_Player_cb_OnStreamInfo(hPlayer, pFileInfo);
free(pFileInfo);
}
break;
case CPNM_FILEOFFSET_SECS:
CPI_Player_cb_OnStreamOffset_Secs(hPlayer, (int)wParam);
break;
case CPNM_FILEOFFSET_PROP:
CPI_Player_cb_OnStreamOffset_Range(hPlayer, (int)wParam);
break;
case CPNM_SYNCCOOKIE:
CPI_Player_cb_OnSyncCookie(hPlayer, (int)wParam);
break;
case CPNM_FOUNDOUTPUTDEVICE:
{
char* pcDeviceName = (char*)wParam;
CPI_Player_cb_OnEnumOutputDevice(hPlayer, pcDeviceName, (int)lParam);
if(pcDeviceName)free(pcDeviceName);
}
break;
case CPNM_SETSTREAMINGSTATE:
CPI_Player_cb_OnStreamStateChange(hPlayer, (BOOL)wParam, (int)lParam);
break;
case MM_MIXM_CONTROL_CHANGE:
{
const DWORD dwControlID = (DWORD)lParam;
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
if(pPlayEngine->m_dwMixerControlID == dwControlID)
CPI_Player_cb_OnVolumeChange(hPlayer, CPI_Player__GetVolume(hPlayer));
}
break;
}
return TRUE;
}
//
//
//
void CPI_Player__OnOutputDeviceChange(CP_HPLAYER hPlayer)
{
CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
CP_CHECKOBJECT(pPlayEngine);
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_ONOUTPUTMODULECHANGE, 0, 0);
}
//
//
//
CPI_Player__SetInternalVolume(CPs_PlayEngine* pPlayEngine, const int iNewVolume)
{
// 發(fā)送消息
PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SETINTERNALVOLUME, (WPARAM)iNewVolume, 0);
}
//
//
//
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -