VolumeOutMaster.cpp
上传用户:oldpeter23
上传日期:2013-01-09
资源大小:1111k
文件大小:15k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. //NetTalk
  2. /*------------------------------------------------------------------------------*
  3.  =============================
  4.    模块名称: VolumeOutMaster.cpp
  5.  =============================
  6.  
  7.  [版权]
  8.  
  9.    2000-2002  115软件工厂  版权所有
  10.                                               
  11. *------------------------------------------------------------------------------*/
  12. #include <Windows.h>
  13. #include "VolumeOutMaster.h"
  14. /*------------------------------------------------------------------------------*/
  15. /////////////////////////////////////////////////////////////////////////////
  16. //  Defines
  17. #define BAD_DWORD (DWORD)-1
  18. #define WND_CLASS_NAME "Master Output Volume Msg Wnd Class"
  19. #define WND_NAME "Master Output Volume Msg Wnd"
  20. /*------------------------------------------------------------------------------*/
  21. /////////////////////////////////////////////////////////////////////////////
  22. //  Globals
  23. PCVolumeOutMaster g_pThis = NULL;
  24. /*------------------------------------------------------------------------------*/
  25. ////////////////////////////////////////////////////////////
  26. /*------------------------------------------------------------------------------*/
  27. //{{{ Audio specific functions
  28. #define AUDFREQ 22050 // Frequency
  29. #define AUDCHANNELS 1 // Number of channels
  30. #define AUDBITSMPL 16 // Number of bits per sample
  31. /*------------------------------------------------------------------------------*/
  32. inline
  33. void SetDeviceType( WAVEFORMATEX* pwfe )
  34. {
  35. memset( pwfe, 0, sizeof(WAVEFORMATEX) );
  36. WORD  nBlockAlign = (AUDCHANNELS*AUDBITSMPL)/8;
  37. DWORD nSamplesPerSec = AUDFREQ;
  38. pwfe->wFormatTag = WAVE_FORMAT_PCM;
  39. pwfe->nChannels = AUDCHANNELS;
  40. pwfe->nBlockAlign = nBlockAlign;
  41. pwfe->nSamplesPerSec = nSamplesPerSec;
  42. pwfe->wBitsPerSample = AUDBITSMPL;
  43. pwfe->nAvgBytesPerSec = nSamplesPerSec*nBlockAlign;
  44. }
  45. //}}} Audio specific functions
  46. /*------------------------------------------------------------------------------*/
  47. /////////////////////////////////////////////////////////////////////////////
  48. //  Implementation
  49. //////////////
  50. CVolumeOutMaster::CVolumeOutMaster()
  51. : m_bOK(false),
  52. m_bInitialized(false),
  53. m_bAvailable(false),
  54. m_uMixerID(0L),
  55. m_dwMixerHandle(0L),
  56. m_hWnd(NULL),
  57. m_dwMinimalVolume(BAD_DWORD),
  58. m_dwMaximalVolume(BAD_DWORD),
  59. m_pfUserSink(NULL),
  60. m_dwUserValue(0L)
  61. {
  62. if ( m_bOK = Init() )
  63. {
  64. g_pThis = this;
  65. if ( !Initialize() )
  66. {
  67. Done();
  68. g_pThis = NULL;
  69. }
  70. }
  71. }
  72. /*------------------------------------------------------------------------------*/
  73. //////////////
  74. CVolumeOutMaster::~CVolumeOutMaster()
  75. {
  76. if ( m_bOK )
  77. Done();
  78. g_pThis = NULL;
  79. }
  80. /*------------------------------------------------------------------------------*/
  81. //////////////
  82. bool CVolumeOutMaster::Init()
  83. {
  84. if ( !mixerGetNumDevs() )
  85. return false;
  86. // Getting Mixer ID
  87. HWAVEOUT hwaveOut;
  88. MMRESULT mmResult;
  89. WAVEFORMATEX WaveFmt;
  90. SetDeviceType( &WaveFmt );
  91. mmResult = waveOutOpen( &hwaveOut, WAVE_MAPPER, &WaveFmt, 0L, 0L, CALLBACK_NULL );
  92. if ( mmResult != MMSYSERR_NOERROR )
  93. {
  94. return false;
  95. } else {
  96. mmResult = mixerGetID( (HMIXEROBJ)hwaveOut, &m_uMixerID, MIXER_OBJECTF_HWAVEOUT );
  97. waveOutClose( hwaveOut );
  98. if ( mmResult != MMSYSERR_NOERROR )
  99. {
  100. return false;
  101. }
  102. }
  103. // Exposing Window to Mixer
  104. WNDCLASSEX wcx;
  105. memset( &wcx, 0, sizeof(WNDCLASSEX) );
  106. wcx.cbSize = sizeof(WNDCLASSEX);
  107. wcx.lpszClassName = WND_CLASS_NAME;
  108. wcx.lpfnWndProc = (WNDPROC)MixerWndProc;
  109. ::RegisterClassEx(&wcx);
  110. m_hWnd = CreateWindow( WND_CLASS_NAME,
  111. WND_NAME,
  112. WS_POPUP | WS_DISABLED,
  113. 0, 0, 0, 0,
  114. NULL, NULL, NULL, NULL );
  115. if ( !m_hWnd )
  116. {
  117. return false;
  118. }
  119. ::ShowWindow(m_hWnd, SW_HIDE);
  120. mmResult = mixerOpen( (LPHMIXER)&m_dwMixerHandle, m_uMixerID, (DWORD)m_hWnd, 0L, CALLBACK_WINDOW );
  121. if ( mmResult != MMSYSERR_NOERROR )
  122. {
  123. ::DestroyWindow( m_hWnd );
  124. return false;
  125. }
  126. return true;
  127. }
  128. /*------------------------------------------------------------------------------*/
  129. //////////////
  130. void CVolumeOutMaster::Done()
  131. {
  132. if ( mixerClose( (HMIXER)m_dwMixerHandle ) != MMSYSERR_NOERROR )
  133. {
  134. }
  135. ::DestroyWindow( m_hWnd );
  136. m_bInitialized = false;
  137. m_bOK = false;
  138. }
  139. /*------------------------------------------------------------------------------*/
  140. //////////////
  141. void CVolumeOutMaster::OnControlChanged( DWORD dwControlID )
  142. {
  143. if ( m_dwVolumeControlID == dwControlID )
  144. {
  145. DWORD dwVolume = GetCurrentVolume();
  146. if ( (dwVolume!=BAD_DWORD) && (m_pfUserSink) )
  147. {
  148. (*m_pfUserSink)( dwVolume, m_dwUserValue );
  149. }
  150. }
  151. }
  152. /*------------------------------------------------------------------------------*/
  153. //////////////
  154. bool CVolumeOutMaster::Initialize()
  155. {
  156. MMRESULT mmResult;
  157. if ( !m_bOK )
  158. return false;
  159. MIXERLINE MixerLine;
  160. memset( &MixerLine, 0, sizeof(MIXERLINE) );
  161. MixerLine.cbStruct = sizeof(MIXERLINE);
  162. MixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
  163. mmResult = mixerGetLineInfo( (HMIXEROBJ)m_dwMixerHandle, &MixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE );
  164. if ( mmResult != MMSYSERR_NOERROR )
  165. {
  166. return false;
  167. }
  168. MIXERCONTROL Control;
  169. memset( &Control, 0, sizeof(MIXERCONTROL) );
  170. Control.cbStruct = sizeof(MIXERCONTROL);
  171. MIXERLINECONTROLS LineControls;
  172. memset( &LineControls, 0, sizeof(MIXERLINECONTROLS) );
  173. LineControls.cbStruct = sizeof(MIXERLINECONTROLS);
  174. LineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
  175. LineControls.dwLineID = MixerLine.dwLineID;
  176. LineControls.cControls = 1;
  177. LineControls.cbmxctrl = sizeof(MIXERCONTROL);
  178. LineControls.pamxctrl = &Control;
  179. mmResult = mixerGetLineControls( (HMIXEROBJ)m_dwMixerHandle, &LineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE );
  180. if ( mmResult == MMSYSERR_NOERROR )
  181. {
  182. if ( !(Control.fdwControl & MIXERCONTROL_CONTROLF_DISABLED) )
  183. {
  184. m_bAvailable = true;
  185. } else {
  186. }
  187. } else {
  188. }
  189. m_nChannelCount = MixerLine.cChannels;
  190. m_dwLineID = LineControls.dwLineID;
  191. m_dwVolumeControlID = Control.dwControlID;
  192. m_dwMinimalVolume = Control.Bounds.dwMinimum;
  193. m_dwMaximalVolume = Control.Bounds.dwMaximum;
  194. m_dwVolumeStep = Control.Metrics.cSteps;
  195. m_bInitialized = true;
  196. return true;
  197. }
  198. /*------------------------------------------------------------------------------*/
  199. //////////////
  200. void CVolumeOutMaster::EnableLine( bool bEnable )
  201. {
  202. if ( !m_bInitialized )
  203. return;
  204. bool bAnyEnabled = false;
  205. MMRESULT mmResult;
  206. MIXERLINE lineDestination;
  207. memset( &lineDestination, 0, sizeof(MIXERLINE) );
  208. lineDestination.cbStruct = sizeof(MIXERLINE);
  209. lineDestination.dwLineID = m_dwLineID;
  210. mmResult = mixerGetLineInfo( (HMIXEROBJ)m_dwMixerHandle, &lineDestination, MIXER_GETLINEINFOF_LINEID );
  211. if ( mmResult != MMSYSERR_NOERROR )
  212. {
  213. if ( bEnable )
  214. {
  215. } else {
  216. }
  217. return;
  218. }
  219. // Getting all line's controls
  220. int nControlCount = lineDestination.cControls;
  221. int nChannelCount = lineDestination.cChannels;
  222. MIXERLINECONTROLS LineControls;
  223. memset( &LineControls, 0, sizeof(MIXERLINECONTROLS) );
  224. MIXERCONTROL* aControls = (MIXERCONTROL*)malloc( nControlCount * sizeof(MIXERCONTROL) );
  225. if ( !aControls )
  226. {
  227. if ( bEnable )
  228. {
  229. } else {
  230. }
  231. return;
  232. }
  233. memset( &aControls[0], 0, sizeof(nControlCount * sizeof(MIXERCONTROL)) );
  234. for ( int i = 0; i < nControlCount; i++ )
  235. {
  236. aControls[i].cbStruct = sizeof(MIXERCONTROL);
  237. }
  238. LineControls.cbStruct = sizeof(MIXERLINECONTROLS);
  239. LineControls.dwLineID = lineDestination.dwLineID;
  240. LineControls.cControls = nControlCount;
  241. LineControls.cbmxctrl = sizeof(MIXERCONTROL);
  242. LineControls.pamxctrl = &aControls[0];
  243. mmResult = mixerGetLineControls( (HMIXEROBJ)m_dwMixerHandle, &LineControls, MIXER_GETLINECONTROLSF_ALL );
  244. if ( mmResult == MMSYSERR_NOERROR )
  245. {
  246. for ( i = 0; i < nControlCount; i++ )
  247. {
  248. LONG lValue;
  249. bool bReadyToSet = false;
  250. switch (aControls[i].dwControlType)
  251. {
  252. case MIXERCONTROL_CONTROLTYPE_MUTE:
  253. lValue = (BOOL)!bEnable;
  254. bReadyToSet = true;
  255. break;
  256. case MIXERCONTROL_CONTROLTYPE_SINGLESELECT:
  257. lValue = (BOOL)bEnable;
  258. bReadyToSet = true;
  259. break;
  260. case MIXERCONTROL_CONTROLTYPE_MUX:
  261. lValue = (BOOL)bEnable;
  262. bReadyToSet = true;
  263. break;
  264. case MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT:
  265. lValue = (BOOL)bEnable;
  266. bReadyToSet = true;
  267. break;
  268. case MIXERCONTROL_CONTROLTYPE_MIXER:
  269. lValue = (BOOL)bEnable;
  270. bReadyToSet = true;
  271. break;
  272. }
  273. if ( bReadyToSet )
  274. {
  275. MIXERCONTROLDETAILS_BOOLEAN* aDetails = NULL;
  276. int nMultipleItems = aControls[i].cMultipleItems;
  277. int nChannels = nChannelCount;
  278. // MIXERCONTROLDETAILS
  279. MIXERCONTROLDETAILS ControlDetails;
  280. memset( &ControlDetails, 0, sizeof(MIXERCONTROLDETAILS) );
  281. ControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
  282. ControlDetails.dwControlID = aControls[i].dwControlID;
  283. if ( aControls[i].fdwControl & MIXERCONTROL_CONTROLF_UNIFORM )
  284. {
  285. nChannels = 1;
  286. }
  287. if ( aControls[i].fdwControl & MIXERCONTROL_CONTROLF_MULTIPLE )
  288. {
  289. nMultipleItems = aControls[i].cMultipleItems;
  290. aDetails = (MIXERCONTROLDETAILS_BOOLEAN*)malloc(nMultipleItems*nChannels*sizeof(MIXERCONTROLDETAILS_BOOLEAN));
  291. if ( !aDetails )
  292. {
  293. if ( bEnable )
  294. {
  295. } else {
  296. }
  297. continue;
  298. }
  299. for ( int nItem = 0; nItem < nMultipleItems; nItem++ )
  300. {
  301. /*
  302. if ( ( aControls[i].dwControlType & MIXERCONTROL_CONTROLTYPE_SINGLESELECT )
  303.   && ( nItem > 0 ) )
  304. {
  305. lValue = (LONG)!((BOOL)lValue);
  306. }
  307. */
  308. for ( int nChannel = 0; nChannel < nChannels; nChannel++ )
  309. {
  310. aDetails[nItem+nChannel].fValue = lValue;
  311. }
  312. }
  313. } else {
  314. nMultipleItems = 0;
  315. aDetails = (MIXERCONTROLDETAILS_BOOLEAN*)malloc(nChannels*sizeof(MIXERCONTROLDETAILS_BOOLEAN));
  316. if ( !aDetails )
  317. {
  318. if ( bEnable )
  319. {
  320. } else {
  321. }
  322. continue;
  323. }
  324. for ( int nChannel = 0; nChannel < nChannels; nChannel++ )
  325. {
  326. aDetails[nChannel].fValue = (LONG)lValue;
  327. }
  328. }
  329. ControlDetails.cChannels = nChannels;
  330. ControlDetails.cMultipleItems = nMultipleItems;
  331. ControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_BOOLEAN);
  332. ControlDetails.paDetails = &aDetails[0];
  333. mmResult = mixerSetControlDetails( (HMIXEROBJ)m_dwMixerHandle, &ControlDetails, 0L );
  334. if ( mmResult == MMSYSERR_NOERROR )
  335. {
  336. if ( bEnable )
  337. {
  338. } else {
  339. }
  340. bAnyEnabled = true;
  341. }
  342. free( aDetails );
  343. }
  344. }
  345. } else {
  346. if ( bEnable )
  347. {
  348. } else {
  349. }
  350. }
  351. free( aControls );
  352. if ( !bAnyEnabled )
  353. {
  354. if ( bEnable )
  355. {
  356. } else {
  357. }
  358. }
  359. }
  360. /*------------------------------------------------------------------------------*/
  361. //////////////////////////////////////////////
  362. // IVolume interface
  363. //////////////
  364. bool CVolumeOutMaster::IsAvailable()
  365. {
  366. return m_bAvailable;
  367. }
  368. /*------------------------------------------------------------------------------*/
  369. //////////////
  370. void CVolumeOutMaster::Enable()
  371. {
  372. EnableLine( true );
  373. }
  374. /*------------------------------------------------------------------------------*/
  375. void CVolumeOutMaster::Disable()
  376. {
  377. EnableLine( false );
  378. }
  379. /*------------------------------------------------------------------------------*/
  380. //////////////
  381. DWORD CVolumeOutMaster::GetVolumeMetric()
  382. {
  383. if ( !m_bAvailable )
  384. return BAD_DWORD;
  385. return m_dwVolumeStep;
  386. }
  387. /*------------------------------------------------------------------------------*/
  388. //////////////
  389. DWORD CVolumeOutMaster::GetMinimalVolume()
  390. {
  391. if ( !m_bAvailable )
  392. return BAD_DWORD;
  393. return m_dwMinimalVolume;
  394. }
  395. /*------------------------------------------------------------------------------*/
  396. //////////////
  397. DWORD CVolumeOutMaster::GetMaximalVolume()
  398. {
  399. if ( !m_bAvailable )
  400. return BAD_DWORD;
  401. return m_dwMaximalVolume;
  402. }
  403. /*------------------------------------------------------------------------------*/
  404. //////////////
  405. DWORD CVolumeOutMaster::GetCurrentVolume()
  406. {
  407. if ( !m_bAvailable )
  408. return BAD_DWORD;
  409. MIXERCONTROLDETAILS_UNSIGNED* aDetails = (MIXERCONTROLDETAILS_UNSIGNED*)malloc(m_nChannelCount*sizeof(MIXERCONTROLDETAILS_UNSIGNED));
  410. if ( !aDetails )
  411. return BAD_DWORD;
  412. MIXERCONTROLDETAILS ControlDetails;
  413. memset( &ControlDetails, 0, sizeof(MIXERCONTROLDETAILS) );
  414. ControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
  415. ControlDetails.dwControlID = m_dwVolumeControlID;
  416. ControlDetails.cChannels = m_nChannelCount;
  417. ControlDetails.cMultipleItems = 0;
  418. ControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
  419. ControlDetails.paDetails = &aDetails[0];
  420. MMRESULT mmResult = mixerGetControlDetails( (HMIXEROBJ)m_dwMixerHandle, &ControlDetails, MIXER_GETCONTROLDETAILSF_VALUE );
  421. DWORD dw = aDetails[0].dwValue;
  422. free( aDetails );
  423. if ( mmResult != MMSYSERR_NOERROR )
  424. {
  425. return BAD_DWORD;
  426. }
  427. return dw;
  428. }
  429. /*------------------------------------------------------------------------------*/
  430. //////////////
  431. void CVolumeOutMaster::SetCurrentVolume( DWORD dwValue )
  432. {
  433. if ( !m_bAvailable || (dwValue<m_dwMinimalVolume) || (dwValue>m_dwMaximalVolume) )
  434. return;
  435. MIXERCONTROLDETAILS_UNSIGNED* aDetails = (MIXERCONTROLDETAILS_UNSIGNED*)malloc(m_nChannelCount*sizeof(MIXERCONTROLDETAILS_UNSIGNED));
  436. if ( !aDetails )
  437. return;
  438. for ( int i = 0; i < m_nChannelCount; i++ )
  439. {
  440. aDetails[i].dwValue = dwValue;
  441. }
  442. MIXERCONTROLDETAILS ControlDetails;
  443. memset( &ControlDetails, 0, sizeof(MIXERCONTROLDETAILS) );
  444. ControlDetails.cbStruct = sizeof(MIXERCONTROLDETAILS);
  445. ControlDetails.dwControlID = m_dwVolumeControlID;
  446. ControlDetails.cChannels = m_nChannelCount;
  447. ControlDetails.cMultipleItems = 0;
  448. ControlDetails.cbDetails = sizeof(MIXERCONTROLDETAILS_UNSIGNED);
  449. ControlDetails.paDetails = &aDetails[0];
  450. MMRESULT mmResult = mixerSetControlDetails( (HMIXEROBJ)m_dwMixerHandle, &ControlDetails, MIXER_SETCONTROLDETAILSF_VALUE );
  451. free( aDetails );
  452. if ( mmResult != MMSYSERR_NOERROR )
  453. {
  454. }
  455. }
  456. /*------------------------------------------------------------------------------*/
  457. //////////////
  458. void CVolumeOutMaster::RegisterNotificationSink( PONMICVOULUMECHANGE pfUserSink, DWORD dwUserValue )
  459. {
  460. m_pfUserSink = pfUserSink;
  461. m_dwUserValue = dwUserValue;
  462. }
  463. /*------------------------------------------------------------------------------*/
  464. ////////////////////////////////////////////////////////////////////////
  465. LRESULT CALLBACK CVolumeOutMaster::MixerWndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
  466. {
  467. if ( uMsg == MM_MIXM_CONTROL_CHANGE )
  468. {
  469. if ( g_pThis )
  470. {
  471. g_pThis->OnControlChanged( (DWORD)lParam );
  472. }
  473. }
  474. return ::DefWindowProc( hwnd, uMsg, wParam, lParam);
  475. }