CPI_Player.c
上传用户:tuheem
上传日期:2007-05-01
资源大小:21889k
文件大小:13k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "globals.h"
  3. #include "CPI_Player.h"
  4. #include "CPI_Player_Messages.h"
  5. CPI_Player__SetInternalVolume(CPs_PlayEngine* pPlayEngine, const int iNewVolume);
  6. CP_HPLAYER CPI_Player__Create(HWND hWndMain)
  7. {
  8.     CPs_PlayEngine* pNewPlayEngine;
  9.     // 线程控制对象
  10.     pNewPlayEngine = (CPs_PlayEngine*)malloc(sizeof(CPs_PlayEngine));
  11.     pNewPlayEngine->m_hWndNotify = hWndMain;
  12.     // 创建事件,当线程准备好输入时,事件将被通知
  13.     pNewPlayEngine->m_hEvtThreadReady = CreateEvent(NULL, FALSE, FALSE, NULL);
  14.     // 创建线程
  15.     pNewPlayEngine->m_hThread = CreateThread(NULL, 0, CPI_Player__EngineEP, pNewPlayEngine, 0, &(pNewPlayEngine->m_dwThreadID) );
  16.     CP_ASSERT(pNewPlayEngine->m_hThread);
  17.     // 等待引擎就绪
  18.     WaitForSingleObject(pNewPlayEngine->m_hEvtThreadReady, INFINITE);
  19.     CloseHandle(pNewPlayEngine->m_hEvtThreadReady);
  20.     pNewPlayEngine->m_hEvtThreadReady = NULL;
  21.     pNewPlayEngine->m_hVolumeMixer = NULL;
  22.     CPI_Player__ReopenMixer((CP_HPLAYER)pNewPlayEngine);
  23.     return (CP_HPLAYER)pNewPlayEngine;
  24. }
  25. //
  26. //
  27. //
  28. void CPI_Player__Destroy(CP_HPLAYER hPlayer)
  29. {
  30.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  31.     CP_CHECKOBJECT(pPlayEngine);
  32.     // 请求线程关闭
  33.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_STOP, 0, 0);
  34.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_QUIT, 0, 0);
  35.     // 关闭音量混合器
  36.     if(pPlayEngine->m_hVolumeMixer)
  37.         mixerClose(pPlayEngine->m_hVolumeMixer);
  38.     // 等待关闭实际上发生
  39.     WaitForSingleObject(pPlayEngine->m_hThread, INFINITE);
  40.     // 清空
  41.     CloseHandle(pPlayEngine->m_hThread);
  42.     free(pPlayEngine);
  43. }
  44. //
  45. //
  46. //
  47. void CPI_Player__ReopenMixer(CP_HPLAYER hPlayer)
  48. {
  49.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  50.     WAVEFORMATEX waveformatex;
  51.     HWAVEOUT hWaveOut;
  52.     CP_CHECKOBJECT(pPlayEngine);
  53.     // 关闭音量混合器
  54.     if(pPlayEngine->m_hVolumeMixer)
  55.     {
  56.         mixerClose(pPlayEngine->m_hVolumeMixer);
  57.         pPlayEngine->m_hVolumeMixer = NULL;
  58.     }
  59.     if(globals.m_enMixerMode == mmMasterVolume || globals.m_enMixerMode == mmWaveVolume)
  60.     {
  61.         // 通过打开波形输出流并由此打开混声器,获得混声器ID
  62.         waveformatex.wFormatTag = WAVE_FORMAT_PCM;
  63.         waveformatex.nChannels = 2;
  64.         waveformatex.nSamplesPerSec = 44100;
  65.         waveformatex.wBitsPerSample = 16;
  66.         waveformatex.nBlockAlign = (waveformatex.nChannels * waveformatex.wBitsPerSample)>>3;
  67.         waveformatex.nAvgBytesPerSec = waveformatex.nSamplesPerSec * waveformatex.nBlockAlign;
  68.         waveformatex.cbSize = 0;
  69.         waveOutOpen( &hWaveOut,
  70.                      WAVE_MAPPER,
  71.                      &waveformatex,
  72.                      0,
  73.                      0, CALLBACK_NULL);
  74.         // 为音量创建一个混声器(mixer)控制 (如果可以)
  75.         if(mixerOpen(&pPlayEngine->m_hVolumeMixer, (UINT)hWaveOut, (DWORD)pPlayEngine->m_hWndNotify, 0, CALLBACK_WINDOW | MIXER_OBJECTF_HWAVEOUT) == MMSYSERR_NOERROR)
  76.         {
  77.             MIXERCAPS mixercaps;
  78.             DWORD dwLineID;
  79.             DWORD dwNumControls;
  80.             MIXERLINECONTROLS linecontrols;
  81.             MIXERCONTROL mixercontrol;
  82.             //  为第一个波形输出设备的扬声器获得目的文件的
  83.             mixerGetDevCaps((UINT)pPlayEngine->m_hVolumeMixer, &mixercaps, sizeof(mixercaps));
  84.             {
  85.                 MIXERLINE mixerline;
  86.                 memset(&mixerline, 0, sizeof(mixerline));
  87.                 mixerline.cbStruct = sizeof(mixerline);
  88.                 if(globals.m_enMixerMode == mmMasterVolume)
  89.                 {
  90.                     mixerline.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
  91.                     mixerGetLineInfo((HMIXEROBJ)pPlayEngine->m_hVolumeMixer,
  92.                                      &mixerline,
  93.                                      MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_COMPONENTTYPE);
  94.                 }
  95.                 else
  96.                 {
  97.                     mixerline.Target.dwType = MIXERLINE_TARGETTYPE_WAVEOUT;
  98.                     mixerline.Target.wMid = mixercaps.wMid;
  99.                     mixerline.Target.wPid = mixercaps.wPid;
  100.                     mixerline.Target.vDriverVersion = mixercaps.vDriverVersion;
  101.                     strncpy(mixerline.Target.szPname, mixercaps.szPname, sizeof(mixerline.Target.szPname));
  102.                     mixerGetLineInfo((HMIXEROBJ)pPlayEngine->m_hVolumeMixer,
  103.                                      &mixerline,
  104.                                      MIXER_OBJECTF_HMIXER | MIXER_GETLINEINFOF_TARGETTYPE);
  105.                 }
  106.                 dwLineID = mixerline.dwLineID;
  107.                 dwNumControls = mixerline.cControls;
  108.             }
  109.             // 获得音量控制器的 controlID 
  110.             memset(&linecontrols, 0, sizeof(linecontrols));
  111.             linecontrols.cbStruct = sizeof(linecontrols);
  112.             linecontrols.dwLineID = dwLineID;
  113.             linecontrols.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
  114.             linecontrols.cControls = 1;
  115.             linecontrols.cbmxctrl = sizeof(MIXERCONTROL);
  116.             linecontrols.pamxctrl = &mixercontrol;
  117.             memset(&mixercontrol, 0, sizeof(mixercontrol));
  118.             mixercontrol.cbStruct = sizeof(mixercontrol);
  119.             mixerGetLineControls((HMIXEROBJ)pPlayEngine->m_hVolumeMixer,
  120.                                  &linecontrols,
  121.                                  MIXER_OBJECTF_HMIXER | MIXER_GETLINECONTROLSF_ONEBYTYPE);
  122.             pPlayEngine->m_dwMixerControlID = mixercontrol.dwControlID;
  123.             CPI_Player__SetInternalVolume(pPlayEngine, 100);
  124.         }
  125.         else
  126.         {
  127.             CP_TRACE0("Failed to open mixer");
  128.             pPlayEngine->m_hVolumeMixer = NULL;
  129.         }
  130.         waveOutClose(hWaveOut);
  131.     }
  132.     else
  133.     {
  134.         CPI_Player__SetInternalVolume(pPlayEngine, globals.m_iVolume);
  135.     }
  136. }
  137. //
  138. //
  139. //
  140. void CPI_Player__OpenFile(CP_HPLAYER hPlayer, const char* pcFilename)
  141. {
  142.     char* pcStringCopy;
  143.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  144.     CP_CHECKOBJECT(pPlayEngine);
  145.     // 对流数据作备份
  146.     STR_AllocSetString(&pcStringCopy, pcFilename, FALSE);
  147.     // 发送消息 (被调用者将释放串)
  148.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_OPENFILE, (WPARAM)pcStringCopy, 0);
  149. }
  150. //
  151. //
  152. //
  153. void CPI_Player__Seek(CP_HPLAYER hPlayer, const int iSeekPercent_Numerator, const int iSeekPercent_Denominator)
  154. {
  155.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  156.     CP_CHECKOBJECT(pPlayEngine);
  157.     // 发送消息
  158.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SEEK, (WPARAM)iSeekPercent_Numerator, (LPARAM)iSeekPercent_Denominator);
  159. }
  160. //
  161. //
  162. //
  163. void CPI_Player__Play(CP_HPLAYER hPlayer)
  164. {
  165.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  166.     CP_CHECKOBJECT(pPlayEngine);
  167.     // 发送消息
  168.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_PLAY, 0, 0);
  169. }
  170. //
  171. //
  172. //
  173. void CPI_Player__Stop(CP_HPLAYER hPlayer)
  174. {
  175.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  176.     CP_CHECKOBJECT(pPlayEngine);
  177.     // 发送消息
  178.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_STOP, 0, 0);
  179. }
  180. //
  181. //
  182. //
  183. void CPI_Player__Pause(CP_HPLAYER hPlayer)
  184. {
  185.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  186.     CP_CHECKOBJECT(pPlayEngine);
  187.     // 发送消息
  188.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_PAUSE, 0, 0);
  189. }
  190. //
  191. //
  192. //
  193. void CPI_Player__BlockMessagesUntilEndOfStream(CP_HPLAYER hPlayer)
  194. {
  195.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  196.     CP_CHECKOBJECT(pPlayEngine);
  197.     // 发送消息
  198.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_BLOCKMSGUNTILENDOFSTREAM, 0, 0);
  199. }
  200. //
  201. //
  202. //
  203. void CPI_Player__SetVolume(CP_HPLAYER hPlayer, const int iNewVolume)
  204. {
  205.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  206.     CP_CHECKOBJECT(pPlayEngine);
  207.     // 通过混声器设置音量
  208.     if(pPlayEngine->m_hVolumeMixer)
  209.     {
  210.         MIXERCONTROLDETAILS_UNSIGNED VolumeLevel;
  211.         MIXERCONTROLDETAILS details;
  212.         details.cbStruct = sizeof(details);
  213.         details.dwControlID = pPlayEngine->m_dwMixerControlID;
  214.         details.cChannels = 1;
  215.         details.hwndOwner = NULL;
  216.         details.cMultipleItems = 0;
  217.         details.cbDetails = sizeof(VolumeLevel);
  218.         details.paDetails = &VolumeLevel;
  219.         VolumeLevel.dwValue = iNewVolume * 0x28F;
  220.         mixerSetControlDetails((HMIXEROBJ)pPlayEngine->m_hVolumeMixer, &details, MIXER_OBJECTF_HMIXER);
  221.     }
  222.     else
  223.         CPI_Player__SetInternalVolume(pPlayEngine, globals.m_iVolume);
  224. }
  225. //
  226. //
  227. //
  228. int CPI_Player__GetVolume(CP_HPLAYER hPlayer)
  229. {
  230.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  231.     CP_CHECKOBJECT(pPlayEngine);
  232.     // 通过混声器得到音量
  233.     if(pPlayEngine->m_hVolumeMixer)
  234.     {
  235.         MIXERCONTROLDETAILS_UNSIGNED VolumeLevel;
  236.         MIXERCONTROLDETAILS details;
  237.         details.cbStruct = sizeof(details);
  238.         details.dwControlID = pPlayEngine->m_dwMixerControlID;
  239.         details.cChannels = 1;
  240.         details.hwndOwner = NULL;
  241.         details.cMultipleItems = 0;
  242.         details.cbDetails = sizeof(VolumeLevel);
  243.         details.paDetails = &VolumeLevel;
  244.         VolumeLevel.dwValue = 0;
  245.         mixerGetControlDetails((HMIXEROBJ)pPlayEngine->m_hVolumeMixer, &details, MIXER_OBJECTF_HMIXER);
  246.         return VolumeLevel.dwValue / 0x28F;
  247.     }
  248.     else
  249.         return globals.m_iVolume;
  250. }
  251. //
  252. //
  253. //
  254. void CPI_Player__SetEQ(CP_HPLAYER hPlayer, const BOOL bEnabled, const int cBands[9])
  255. {
  256.     int iEQBandIDX;
  257.     CPs_EQSettings* pNewEQSettings;
  258.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  259.     CP_CHECKOBJECT(pPlayEngine);
  260.     // 设置params 
  261.     pNewEQSettings = (CPs_EQSettings*)malloc(sizeof(*pNewEQSettings));
  262.     pNewEQSettings->m_bEnabled = bEnabled;
  263.     // 设置带 - 由于一些原因,UI 基于1 !!!
  264.     for(iEQBandIDX = 0; iEQBandIDX < 8; iEQBandIDX++)
  265.         pNewEQSettings->m_aryBands[iEQBandIDX] = (char)cBands[iEQBandIDX+1];
  266.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SETEQSETTINGS, (WPARAM)pNewEQSettings, 0);
  267. }
  268. //
  269. //
  270. //
  271. void CPI_Player__EnumOutputDevices(CP_HPLAYER hPlayer)
  272. {
  273.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  274.     CP_CHECKOBJECT(pPlayEngine);
  275.     // 发送消息
  276.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_ENUMOUTPUTDEVICES, 0, 0);
  277. }
  278. //
  279. //
  280. //
  281. void CPI_Player__SendSyncCookie(CP_HPLAYER hPlayer, const int iCookie)
  282. {
  283.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  284.     CP_CHECKOBJECT(pPlayEngine);
  285.     // 发送消息
  286.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SENDSYNCCOOKIE, (WPARAM)iCookie, 0);
  287. }
  288. //
  289. //
  290. //
  291. void CPI_Player__SetPositionRange(CP_HPLAYER hPlayer, const int iRange)
  292. {
  293.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  294.     CP_CHECKOBJECT(pPlayEngine);
  295.     // 发送消息
  296.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SETPROGRESSTRACKLENGTH, (WPARAM)iRange, 0);
  297. }
  298. //
  299. //
  300. //
  301. void CPI_Player__AssociateFileExtensions(CP_HPLAYER hPlayer)
  302. {
  303.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  304.     CP_CHECKOBJECT(pPlayEngine);
  305.     // 发送消息
  306.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_ASSOCIATEFILEEXTENSIONS, 0, 0);
  307. }
  308. //
  309. //
  310. //
  311. BOOL CPI_Player__HandleNotifyMessages(CP_HPLAYER hPlayer, UINT uiMessage, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
  312. {
  313.     // 如果不是为此目的的消息,则忽略之
  314.     if( (uiMessage < CPNM_first || uiMessage > CPNM_last)
  315.             && uiMessage != MM_MIXM_CONTROL_CHANGE)
  316.     {
  317.         return FALSE;
  318.     }
  319.     // 解码消息
  320.     switch(uiMessage)
  321.     {
  322.     case CPNM_PLAYERSTATE:
  323.         {
  324.             CPe_PlayerState enNewState = (CPe_PlayerState)wParam;
  325.             CPI_Player_cb_OnPlayerState(hPlayer, enNewState);
  326.         }
  327.         break;
  328.     case CPNM_FILEINFO:
  329.         {
  330.             CPs_FileInfo* pFileInfo = (CPs_FileInfo*)wParam;
  331.             CPI_Player_cb_OnStreamInfo(hPlayer, pFileInfo);
  332.             free(pFileInfo);
  333.         }
  334.         break;
  335.     case CPNM_FILEOFFSET_SECS:
  336.         CPI_Player_cb_OnStreamOffset_Secs(hPlayer, (int)wParam);
  337.         break;
  338.     case CPNM_FILEOFFSET_PROP:
  339.         CPI_Player_cb_OnStreamOffset_Range(hPlayer, (int)wParam);
  340.         break;
  341.     case CPNM_SYNCCOOKIE:
  342.         CPI_Player_cb_OnSyncCookie(hPlayer, (int)wParam);
  343.         break;
  344.     case CPNM_FOUNDOUTPUTDEVICE:
  345.         {
  346.             char* pcDeviceName = (char*)wParam;
  347.             CPI_Player_cb_OnEnumOutputDevice(hPlayer, pcDeviceName, (int)lParam);
  348.             if(pcDeviceName)free(pcDeviceName);
  349.         }
  350.         break;
  351.     case CPNM_SETSTREAMINGSTATE:
  352.         CPI_Player_cb_OnStreamStateChange(hPlayer, (BOOL)wParam, (int)lParam);
  353.         break;
  354.     case MM_MIXM_CONTROL_CHANGE:
  355.         {
  356.             const DWORD dwControlID = (DWORD)lParam;
  357.             CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  358.             CP_CHECKOBJECT(pPlayEngine);
  359.             if(pPlayEngine->m_dwMixerControlID == dwControlID)
  360.                 CPI_Player_cb_OnVolumeChange(hPlayer, CPI_Player__GetVolume(hPlayer));
  361.         }
  362.         break;
  363.     }
  364.     return TRUE;
  365. }
  366. //
  367. //
  368. //
  369. void CPI_Player__OnOutputDeviceChange(CP_HPLAYER hPlayer)
  370. {
  371.     CPs_PlayEngine* pPlayEngine = (CPs_PlayEngine*)hPlayer;
  372.     CP_CHECKOBJECT(pPlayEngine);
  373.     // 发送消息
  374.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_ONOUTPUTMODULECHANGE, 0, 0);
  375. }
  376. //
  377. //
  378. //
  379. CPI_Player__SetInternalVolume(CPs_PlayEngine* pPlayEngine, const int iNewVolume)
  380. {
  381.     // 发送消息
  382.     PostThreadMessage(pPlayEngine->m_dwThreadID, CPTM_SETINTERNALVOLUME, (WPARAM)iNewVolume, 0);
  383. }
  384. //
  385. //
  386. //