Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

518 lines
13 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: commands.c
  3. *
  4. * Executes the users commands.
  5. *
  6. *
  7. * Created: 18-11-93
  8. * Author: Stephen Estrop [StephenE]
  9. *
  10. * Copyright (c) 1993 Microsoft Corporation
  11. \**************************************************************************/
  12. #pragma warning( once : 4201 4214 )
  13. #define NOOLE
  14. #include <windows.h> /* required for all Windows applications */
  15. #include <windowsx.h>
  16. #include <string.h>
  17. #include <malloc.h>
  18. #include <stdarg.h>
  19. #include <stdio.h>
  20. #include "playres.h"
  21. #include "cdplayer.h"
  22. #include "ledwnd.h"
  23. #include "cdapi.h"
  24. #include "scan.h"
  25. #include "trklst.h"
  26. #include "database.h"
  27. #include "commands.h"
  28. #define PREVTRAK_TIMELIMIT 3 //seconds
  29. extern IMMFWNotifySink* g_pSink;
  30. /******************************Public*Routine******************************\
  31. * CdPlayerEjectCmd
  32. *
  33. *
  34. *
  35. * History:
  36. * 18-11-93 - StephenE - Created
  37. *
  38. \**************************************************************************/
  39. void
  40. CdPlayerEjectCmd(
  41. void
  42. )
  43. {
  44. if (g_State & CD_PAUSED) {
  45. g_State &= (~(CD_PAUSED_AND_MOVED | CD_PAUSED));
  46. }
  47. if (g_State & CD_PLAYING) {
  48. g_State &= ~CD_PLAYING;
  49. g_State |= CD_STOPPED;
  50. }
  51. if (EjectTheCdromDisc(g_CurrCdrom))
  52. {
  53. g_State = (CD_NO_CD | CD_STOPPED);
  54. SetPlayButtonsEnableState();
  55. TimeAdjustInitialize( g_CurrCdrom );
  56. g_pSink->OnEvent(MMEVENT_ONMEDIAUNLOADED,NULL);
  57. }
  58. }
  59. /******************************Public*Routine******************************\
  60. * CdPlayerPlayCmd
  61. *
  62. *
  63. *
  64. * History:
  65. * 18-11-93 - StephenE - Created
  66. *
  67. \**************************************************************************/
  68. void
  69. CdPlayerPlayCmd(
  70. void
  71. )
  72. {
  73. /*
  74. ** If we can't lock all the cdrom devices
  75. ** don't do anything. The user will have press
  76. ** the play button again.
  77. */
  78. if ( LockALLTableOfContents() ) {
  79. if (g_State & CD_LOADED ) {
  80. if ((g_State & CD_STOPPED) && PlayCurrTrack( g_CurrCdrom )) {
  81. g_State &= ~CD_STOPPED;
  82. g_State |= CD_PLAYING;
  83. }
  84. else if ( g_State & CD_PAUSED ) {
  85. if ( g_State & CD_PAUSED_AND_MOVED ) {
  86. g_State &= ~CD_PAUSED_AND_MOVED;
  87. g_State |= CD_PLAYING;
  88. if ( SeekToCurrSecond( g_CurrCdrom ) ) {
  89. g_State &= ~CD_PAUSED;
  90. g_State |= CD_PLAYING;
  91. }
  92. else {
  93. g_State &= ~CD_PLAYING;
  94. }
  95. }
  96. else if ( ResumeTheCdromDrive( g_CurrCdrom ) ) {
  97. g_State &= ~CD_PAUSED;
  98. g_State |= CD_PLAYING;
  99. }
  100. UpdateDisplay( DISPLAY_UPD_LED );
  101. }
  102. if (g_State & CD_PLAYING)
  103. {
  104. g_pSink->OnEvent(MMEVENT_ONPLAY,NULL);
  105. }
  106. }
  107. else {
  108. #if DBG
  109. dprintf( TEXT("Failing play because NO disc loaded") );
  110. #endif
  111. }
  112. SetPlayButtonsEnableState();
  113. }
  114. }
  115. /******************************Public*Routine******************************\
  116. * CdPlayerPauseCmd
  117. *
  118. *
  119. *
  120. * History:
  121. * 18-11-93 - StephenE - Created
  122. *
  123. \**************************************************************************/
  124. void
  125. CdPlayerPauseCmd(
  126. void
  127. )
  128. {
  129. /*
  130. ** If we can't lock all the cdrom devices
  131. ** don't do anything. The user will have press
  132. ** the pause button again.
  133. */
  134. if ( LockALLTableOfContents() ) {
  135. if ( g_State & CD_PLAYING )
  136. {
  137. if ( PauseTheCdromDrive( g_CurrCdrom ) )
  138. {
  139. g_State &= ~CD_PLAYING;
  140. g_State |= CD_PAUSED;
  141. g_pSink->OnEvent(MMEVENT_ONPAUSE,NULL);
  142. }
  143. }
  144. else if ( g_State & CD_PAUSED )
  145. {
  146. if ( g_State & CD_PAUSED_AND_MOVED ) {
  147. g_State &= ~CD_PAUSED_AND_MOVED;
  148. g_State |= CD_PLAYING;
  149. if ( SeekToCurrSecond( g_CurrCdrom ) ) {
  150. g_State &= ~CD_PAUSED;
  151. g_State |= CD_PLAYING;
  152. }
  153. else {
  154. g_State &= ~CD_PLAYING;
  155. }
  156. }
  157. else if ( ResumeTheCdromDrive( g_CurrCdrom ) ) {
  158. g_State &= ~CD_PAUSED;
  159. g_State |= CD_PLAYING;
  160. }
  161. UpdateDisplay( DISPLAY_UPD_LED );
  162. if (g_State & CD_PLAYING)
  163. {
  164. g_pSink->OnEvent(MMEVENT_ONPLAY,NULL);
  165. }
  166. }
  167. SetPlayButtonsEnableState();
  168. }
  169. }
  170. /******************************Public*Routine******************************\
  171. * CdPlayerStopCmd
  172. *
  173. *
  174. *
  175. * History:
  176. * 18-11-93 - StephenE - Created
  177. *
  178. \**************************************************************************/
  179. void
  180. CdPlayerStopCmd(
  181. void
  182. )
  183. {
  184. /*
  185. ** If we can't lock all the cdrom devices
  186. ** don't do anything. The user will have press
  187. ** the stop button again.
  188. */
  189. if ( LockALLTableOfContents() ) {
  190. BOOL bPlaying, bPaused;
  191. bPlaying = g_State & CD_PLAYING;
  192. bPaused = g_State & CD_PAUSED;
  193. if ( (bPlaying || bPaused) && StopTheCdromDrive(g_CurrCdrom) ) {
  194. g_State &= ~(bPlaying ? CD_PLAYING : CD_PAUSED);
  195. g_State |= CD_STOPPED;
  196. /*
  197. ** Stop the current play operation and seek to the first
  198. ** playable track.
  199. */
  200. CURRTRACK(g_CurrCdrom) = FindFirstTrack( g_CurrCdrom );
  201. TimeAdjustSkipToTrack( g_CurrCdrom, CURRTRACK(g_CurrCdrom) );
  202. UpdateDisplay( DISPLAY_UPD_LED | DISPLAY_UPD_TRACK_TIME |
  203. DISPLAY_UPD_TRACK_NAME );
  204. SetPlayButtonsEnableState();
  205. // Stop it again!!!
  206. // This is to prevent a strange bug with NEC 4x,6x players
  207. // Where a SEEK command in TimeAdjustSkipToTrack causes
  208. // The ejection mechanism to get locked.
  209. if (StopTheCdromDrive (g_CurrCdrom))
  210. {
  211. g_pSink->OnEvent(MMEVENT_ONSTOP,NULL);
  212. }
  213. }
  214. }
  215. }
  216. /******************************Public*Routine******************************\
  217. * CdPlayerPrevTrackCmd
  218. *
  219. *
  220. *
  221. * History:
  222. * 18-11-93 - StephenE - Created
  223. *
  224. \**************************************************************************/
  225. void
  226. CdPlayerPrevTrackCmd(
  227. void
  228. )
  229. {
  230. /*
  231. ** If we can't lock all the cdrom devices
  232. ** don't do anything. The user will have press
  233. ** the previous track button again.
  234. */
  235. if ( LockALLTableOfContents() ) {
  236. DWORD dwOldState;
  237. int i, j;
  238. PTRACK_PLAY tr;
  239. if ( (CDTIME(g_CurrCdrom).TrackCurSec <= PREVTRAK_TIMELIMIT)
  240. && (CDTIME(g_CurrCdrom).TrackCurMin == 0) ) {
  241. dwOldState = g_State;
  242. i = g_CurrCdrom;
  243. tr = FindPrevTrack( g_CurrCdrom, g_fContinuous );
  244. if ( tr == NULL ) {
  245. /*
  246. ** If we were Paused or Playing fake a press on the
  247. ** "stop" button
  248. */
  249. if ( g_State & (CD_PLAYING | CD_PAUSED) ) {
  250. SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_STOP)],
  251. WM_LBUTTONDOWN, 0, 0L );
  252. SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_STOP)],
  253. WM_LBUTTONUP, 0, 0L );
  254. }
  255. }
  256. else {
  257. TimeAdjustSkipToTrack( g_CurrCdrom, tr );
  258. if ( (i != g_CurrCdrom) && (dwOldState & CD_PLAYING) )
  259. {
  260. j = g_CurrCdrom;
  261. g_CurrCdrom = i;
  262. //don't allow the ledwnd to paint
  263. LockWindowUpdate(g_hwndControls[INDEX(IDC_LED)]);
  264. SwitchToCdrom( j, FALSE );
  265. LockWindowUpdate(NULL);
  266. //switchtocdrom command stopped drive, setting us back to track 1...
  267. //reset to correct track
  268. TimeAdjustSkipToTrack( g_CurrCdrom, tr );
  269. SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_PLAY)],
  270. WM_LBUTTONDOWN, 0, 0L );
  271. SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_PLAY)],
  272. WM_LBUTTONUP, 0, 0L );
  273. }
  274. }
  275. }
  276. else {
  277. TimeAdjustSkipToTrack( g_CurrCdrom, CURRTRACK( g_CurrCdrom ) );
  278. }
  279. }
  280. }
  281. /******************************Public*Routine******************************\
  282. * CdPlayerNextTrackCmd
  283. *
  284. *
  285. *
  286. * History:
  287. * 18-11-93 - StephenE - Created
  288. *
  289. \**************************************************************************/
  290. void
  291. CdPlayerNextTrackCmd(
  292. void
  293. )
  294. {
  295. /*
  296. ** If we can't lock all the cdrom devices
  297. ** don't do anything. The user will have press
  298. ** the next track button again.
  299. */
  300. if ( LockALLTableOfContents() ) {
  301. DWORD dwOldState;
  302. PTRACK_PLAY tr;
  303. dwOldState = g_State;
  304. tr = FindNextTrack( g_fContinuous );
  305. if ( tr == NULL ) {
  306. /*
  307. ** If the CD is playing fake a press on the "stop" button
  308. ** otherwise call the stop function directly.
  309. */
  310. if ( g_State & (CD_PLAYING | CD_PAUSED) ) {
  311. SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_STOP)],
  312. WM_LBUTTONDOWN, 0, 0L );
  313. SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_STOP)],
  314. WM_LBUTTONUP, 0, 0L );
  315. }
  316. else {
  317. /*
  318. ** Seek to the first playable track.
  319. */
  320. CURRTRACK(g_CurrCdrom) = FindFirstTrack( g_CurrCdrom );
  321. if (CURRTRACK(g_CurrCdrom) != NULL ) {
  322. TimeAdjustSkipToTrack( g_CurrCdrom,
  323. CURRTRACK(g_CurrCdrom) );
  324. UpdateDisplay( DISPLAY_UPD_LED | DISPLAY_UPD_TRACK_TIME |
  325. DISPLAY_UPD_TRACK_NAME );
  326. SetPlayButtonsEnableState();
  327. }
  328. }
  329. }
  330. else {
  331. if ( g_LastCdrom != g_CurrCdrom) {
  332. SwitchToCdrom( g_CurrCdrom,FALSE);
  333. TimeAdjustSkipToTrack( g_CurrCdrom, tr );
  334. if ( dwOldState & CD_PLAYING ) {
  335. SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_PLAY)],
  336. WM_LBUTTONDOWN, 0, 0L );
  337. SendMessage( g_hwndControls[INDEX(IDM_PLAYBAR_PLAY)],
  338. WM_LBUTTONUP, 0, 0L );
  339. }
  340. }
  341. else {
  342. TimeAdjustSkipToTrack( g_CurrCdrom, tr );
  343. }
  344. }
  345. }
  346. }
  347. /******************************Public*Routine******************************\
  348. * CdPlayerSeekCmd
  349. *
  350. * How Seek works.
  351. *
  352. * When the user presses a seek button (forwards or backwards) this function
  353. * gets called. The cdplayer can be in three possible states:
  354. *
  355. * 1. Playing
  356. * 2. Paused
  357. * 3. Stopped
  358. *
  359. * In state 1 (playing) we pause the device and alter its global state flags
  360. * to show that it was playing (CD_WAS_PLAYING). This is so that we can
  361. * return to the playing state when the user stops seeking.
  362. *
  363. * We then start a timer. We always call the timer function, this means
  364. * that we will allways skip one second no matter how quickly the user
  365. * clicks the seek button. The timer just increments (or decrements) the
  366. * current play position according to the currrent play list. When the users
  367. * releases the seek button we stop the timer and resume playing if the
  368. * CD_WAS_PLAYING flag was set.
  369. *
  370. * The interesting case is when we try to seek beyond the end of the current
  371. * play list. We detect this by testing the state of CURRTRACK(g_CurrCdrom).
  372. * If NULL we have come to the end of the play list. If we were paused or
  373. * previously playing we fake a stop command by sending a WM_LBUTTONDOWN,
  374. * WM_LBUTTONUP message pair to the stop button. This causes the focus
  375. * to be moved from the currently pressed seek button, which means that
  376. * this function will get called BEFORE the CdPlayerStopCmd function. So
  377. * by the time CdPlayerStopCmd gets called the correct playing state of
  378. * the cdrom device would have been restored by the code below.
  379. *
  380. *
  381. * History:
  382. * 18-11-93 - StephenE - Created
  383. *
  384. \**************************************************************************/
  385. void
  386. CdPlayerSeekCmd(
  387. HWND hwnd,
  388. BOOL fStart,
  389. UINT uDirection
  390. )
  391. {
  392. UINT_PTR rc;
  393. BOOL frc;
  394. if ( fStart ) {
  395. if (g_State & CD_PLAYING) {
  396. g_State &= ~CD_PLAYING;
  397. g_State |= CD_WAS_PLAYING;
  398. PauseTheCdromDrive( g_CurrCdrom );
  399. }
  400. g_State |= CD_SEEKING;
  401. rc = SetTimer( hwnd, uDirection, SKIPBEAT_TIMER_RATE,
  402. (TIMERPROC)SkipBeatTimerProc );
  403. ASSERT(rc != 0);
  404. SkipBeatTimerProc( hwnd, WM_TIMER, uDirection, 0L );
  405. }
  406. else {
  407. g_State &= ~CD_SEEKING;
  408. if (g_State & CD_WAS_PLAYING) {
  409. g_State &= ~CD_WAS_PLAYING;
  410. g_State |= CD_PLAYING;
  411. }
  412. if ( g_State & CD_PAUSED ) {
  413. g_State |= CD_PAUSED_AND_MOVED;
  414. }
  415. else {
  416. SeekToCurrSecond( g_CurrCdrom );
  417. }
  418. frc = KillTimer( hwnd, uDirection );
  419. ASSERT(frc != FALSE);
  420. }
  421. }