MciPlayer.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #include "audio/win32/MciPlayer.h"
  2. #include <tchar.h>
  3. #include "platform/CCFileUtils.h"
  4. #define WIN_CLASS_NAME "CocosDenshionCallbackWnd"
  5. #define BREAK_IF(cond) if (cond) break;
  6. namespace CocosDenshion {
  7. static HINSTANCE s_hInstance;
  8. static MCIERROR s_mciError;
  9. LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
  10. MciPlayer::MciPlayer()
  11. : _wnd(NULL)
  12. , _dev(0L)
  13. , _soundID(0)
  14. , _times(0)
  15. , _playing(false)
  16. , strExt("")
  17. {
  18. if (! s_hInstance)
  19. {
  20. s_hInstance = GetModuleHandle( NULL ); // Grab An Instance For Our Window
  21. WNDCLASS wc; // Windows Class Structure
  22. // Redraw On Size, And Own DC For Window.
  23. wc.style = 0;
  24. wc.lpfnWndProc = _SoundPlayProc; // WndProc Handles Messages
  25. wc.cbClsExtra = 0; // No Extra Window Data
  26. wc.cbWndExtra = 0; // No Extra Window Data
  27. wc.hInstance = s_hInstance; // Set The Instance
  28. wc.hIcon = 0; // Load The Default Icon
  29. wc.hCursor = LoadCursor( NULL, IDC_ARROW ); // Load The Arrow Pointer
  30. wc.hbrBackground = NULL; // No Background Required For GL
  31. wc.lpszMenuName = NULL; // We Don't Want A Menu
  32. wc.lpszClassName = _T(WIN_CLASS_NAME); // Set The Class Name
  33. if (! RegisterClass(&wc)
  34. && 1410 != GetLastError())
  35. {
  36. return;
  37. }
  38. }
  39. _wnd = CreateWindowEx(
  40. WS_EX_APPWINDOW, // Extended Style For The Window
  41. _T(WIN_CLASS_NAME), // Class Name
  42. NULL, // Window Title
  43. WS_POPUPWINDOW,/*WS_OVERLAPPEDWINDOW*/ // Defined Window Style
  44. 0, 0, // Window Position
  45. 0, // Window Width
  46. 0, // Window Height
  47. NULL, // No Parent Window
  48. NULL, // No Menu
  49. s_hInstance, // Instance
  50. NULL );
  51. if (_wnd)
  52. {
  53. SetWindowLongPtr(_wnd, GWLP_USERDATA, (LONG_PTR)this);
  54. }
  55. }
  56. MciPlayer::~MciPlayer()
  57. {
  58. Close();
  59. DestroyWindow(_wnd);
  60. }
  61. void MciPlayer::Open(const char* pFileName, UINT uId)
  62. {
  63. // WCHAR * pBuf = NULL;
  64. do
  65. {
  66. BREAK_IF(! pFileName || ! _wnd);
  67. int nLen = (int)strlen(pFileName);
  68. BREAK_IF(! nLen);
  69. // pBuf = new WCHAR[nLen + 1];
  70. // BREAK_IF(! pBuf);
  71. // MultiByteToWideChar(CP_ACP, 0, pFileName, nLen + 1, pBuf, nLen + 1);
  72. strExt = cocos2d::FileUtils::getInstance()->getFileExtension(pFileName);
  73. Close();
  74. MCI_OPEN_PARMS mciOpen = {0};
  75. MCIERROR mciError;
  76. mciOpen.lpstrDeviceType = (LPCTSTR)MCI_ALL_DEVICE_ID;
  77. WCHAR* fileNameWideChar = new WCHAR[nLen + 1];
  78. BREAK_IF(! fileNameWideChar);
  79. MultiByteToWideChar(CP_ACP, 0, pFileName, nLen + 1, fileNameWideChar, nLen + 1);
  80. mciOpen.lpstrElementName = fileNameWideChar;
  81. mciError = mciSendCommand(0,MCI_OPEN, MCI_OPEN_ELEMENT, reinterpret_cast<DWORD_PTR>(&mciOpen));
  82. CC_SAFE_DELETE_ARRAY(mciOpen.lpstrElementName);
  83. BREAK_IF(mciError);
  84. _dev = mciOpen.wDeviceID;
  85. _soundID = uId;
  86. _playing = false;
  87. } while (0);
  88. }
  89. void MciPlayer::Play(UINT uTimes /* = 1 */)
  90. {
  91. if (! _dev)
  92. {
  93. return;
  94. }
  95. MCI_PLAY_PARMS mciPlay = {0};
  96. mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(_wnd);
  97. s_mciError = mciSendCommand(_dev,MCI_PLAY, MCI_FROM|MCI_NOTIFY,reinterpret_cast<DWORD_PTR>(&mciPlay));
  98. if (! s_mciError)
  99. {
  100. _playing = true;
  101. _times = uTimes;
  102. }
  103. }
  104. void MciPlayer::Close()
  105. {
  106. if (_playing)
  107. {
  108. Stop();
  109. }
  110. if (_dev)
  111. {
  112. _SendGenericCommand(MCI_CLOSE);
  113. }
  114. _dev = 0;
  115. _playing = false;
  116. }
  117. void MciPlayer::Pause()
  118. {
  119. _SendGenericCommand(MCI_PAUSE);
  120. _playing = false;
  121. }
  122. void MciPlayer::Resume()
  123. {
  124. if (strExt == ".mid")
  125. {
  126. // midi not support MCI_RESUME, should get the position and use MCI_FROM
  127. MCI_STATUS_PARMS mciStatusParms;
  128. MCI_PLAY_PARMS mciPlayParms;
  129. mciStatusParms.dwItem = MCI_STATUS_POSITION;
  130. _SendGenericCommand(MCI_STATUS, MCI_STATUS_ITEM, reinterpret_cast<DWORD_PTR>(&mciStatusParms)); // MCI_STATUS
  131. mciPlayParms.dwFrom = mciStatusParms.dwReturn; // get position
  132. _SendGenericCommand(MCI_PLAY, MCI_FROM, reinterpret_cast<DWORD_PTR>(&mciPlayParms)); // MCI_FROM
  133. }
  134. else
  135. {
  136. _SendGenericCommand(MCI_RESUME);
  137. _playing = true;
  138. }
  139. }
  140. void MciPlayer::Stop()
  141. {
  142. _SendGenericCommand(MCI_STOP);
  143. _playing = false;
  144. _times = 0;
  145. }
  146. void MciPlayer::Rewind()
  147. {
  148. if (! _dev)
  149. {
  150. return;
  151. }
  152. mciSendCommand(_dev, MCI_SEEK, MCI_SEEK_TO_START, 0);
  153. MCI_PLAY_PARMS mciPlay = {0};
  154. mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(_wnd);
  155. _playing = mciSendCommand(_dev, MCI_PLAY, MCI_NOTIFY,reinterpret_cast<DWORD_PTR>(&mciPlay)) ? false : true;
  156. }
  157. bool MciPlayer::IsPlaying()
  158. {
  159. return _playing;
  160. }
  161. UINT MciPlayer::GetSoundID()
  162. {
  163. return _soundID;
  164. }
  165. //////////////////////////////////////////////////////////////////////////
  166. // private member
  167. //////////////////////////////////////////////////////////////////////////
  168. void MciPlayer::_SendGenericCommand( int nCommand, DWORD_PTR param1 /*= 0*/, DWORD_PTR parma2 /*= 0*/ )
  169. {
  170. if (! _dev)
  171. {
  172. return;
  173. }
  174. mciSendCommand(_dev, nCommand, param1, parma2);
  175. }
  176. //////////////////////////////////////////////////////////////////////////
  177. // static function
  178. //////////////////////////////////////////////////////////////////////////
  179. LRESULT WINAPI _SoundPlayProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
  180. {
  181. MciPlayer * pPlayer = NULL;
  182. if (MM_MCINOTIFY == Msg
  183. && MCI_NOTIFY_SUCCESSFUL == wParam
  184. &&(pPlayer = (MciPlayer *)GetWindowLongPtr(hWnd, GWLP_USERDATA)))
  185. {
  186. if (pPlayer->_times)
  187. {
  188. --pPlayer->_times;
  189. }
  190. if (pPlayer->_times)
  191. {
  192. mciSendCommand(lParam, MCI_SEEK, MCI_SEEK_TO_START, 0);
  193. MCI_PLAY_PARMS mciPlay = {0};
  194. mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(hWnd);
  195. mciSendCommand(lParam, MCI_PLAY, MCI_NOTIFY,reinterpret_cast<DWORD_PTR>(&mciPlay));
  196. }
  197. else
  198. {
  199. pPlayer->_playing = false;
  200. }
  201. return 0;
  202. }
  203. return DefWindowProc(hWnd, Msg, wParam, lParam);
  204. }
  205. } // end of namespace CocosDenshion