Windows NT 4.0 source code leak
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.

330 lines
11 KiB

4 years ago
  1. /******************************************************************************
  2. Copyright (C) Microsoft Corporation 1985-1991. All rights reserved.
  3. Title: foramts.c - Multimedia Systems Media Control Interface
  4. Contains specific mci time format conversion functions
  5. Version: 1.00
  6. Date: 7-MAR-1991
  7. Author: Greg Simons
  8. ------------------------------------------------------------------------------
  9. Change log:
  10. DATE REV DESCRIPTION
  11. ----------- ----- -----------------------------------------------------------
  12. 7-MAR-1991 GregSi Original
  13. *****************************************************************************/
  14. #define UNICODE
  15. //MMSYSTEM
  16. #define MMNOSOUND - Sound support
  17. #define MMNOWAVE - Waveform support
  18. #define MMNOAUX - Auxiliary output support
  19. #define MMNOJOY - Joystick support
  20. //MMDDK
  21. #define NOWAVEDEV - Waveform support
  22. #define NOAUXDEV - Auxiliary output support
  23. #define NOJOYDEV - Joystick support
  24. #include <windows.h>
  25. #include <mmsystem.h>
  26. #include <mmddk.h>
  27. #include "mmsys.h"
  28. #include "list.h"
  29. #include "mciseq.h"
  30. /**************************** PRIVATE PROTOTYPES *************************/
  31. PRIVATE DWORD NEAR PASCAL FPSDisplay(DWORD dwDisplayType);
  32. PRIVATE DWORD NEAR PASCAL FPSFile(int wFileDiv);
  33. PRIVATE DWORD NEAR PASCAL HMSFToFrames(DWORD dwCurrent, DWORD dwFormat);
  34. PRIVATE DWORD NEAR PASCAL HMSFToMS(DWORD dwHmsf, DWORD dwFormat);
  35. PRIVATE DWORD NEAR PASCAL FramesToHMSF(DWORD dwFrames, DWORD dwFormat);
  36. /**************************** PRIVATE FUNCTIONS *************************/
  37. PRIVATE DWORD NEAR PASCAL FPSDisplay(DWORD dwDisplayType)
  38. // return the frames per second for smpte display types
  39. // (utility function for format conversion routines)
  40. {
  41. switch (dwDisplayType)
  42. {
  43. case MCI_FORMAT_SMPTE_24:
  44. return 24;
  45. case MCI_FORMAT_SMPTE_25:
  46. return 25;
  47. case MCI_FORMAT_SMPTE_30DROP:
  48. case MCI_FORMAT_SMPTE_30:
  49. return 30;
  50. #ifdef DEBUG
  51. default:
  52. return 0;
  53. #endif
  54. } //switch
  55. }
  56. PRIVATE DWORD NEAR PASCAL FPSFile(int wFileDiv)
  57. {
  58. // returns frames per second based file division type
  59. switch (wFileDiv)
  60. {
  61. case SEQ_DIV_SMPTE_24:
  62. return 24;
  63. case SEQ_DIV_SMPTE_25:
  64. return 25;
  65. case SEQ_DIV_SMPTE_30:
  66. case SEQ_DIV_SMPTE_30DROP:
  67. return 30;
  68. #ifdef DEBUG
  69. default:
  70. return 0;
  71. #endif
  72. } //switch
  73. }
  74. PRIVATE DWORD NEAR PASCAL HMSFToFrames(DWORD dwCurrent, DWORD dwFormat)
  75. /* convert from hmsf (colonized) format to raw frames */
  76. {
  77. DWORD dwReturn;
  78. HMSF hmsf = * ((HMSF FAR *) &dwCurrent); // cast dwCurrent to hmsf
  79. int fps = (int)FPSDisplay(dwFormat);
  80. dwReturn = ((DWORD)hmsf.hours * 60 * 60 * fps) +
  81. ((DWORD)hmsf.minutes * 60 * fps) +
  82. ((DWORD)hmsf.seconds * fps) +
  83. hmsf.frames;
  84. return dwReturn;
  85. }
  86. PRIVATE DWORD NEAR PASCAL HMSFToMS(DWORD dwHmsf, DWORD dwFormat)
  87. // convert hmsf (colonized) format to milliseconds
  88. {
  89. DWORD dwReturn;
  90. DWORD dwFrames = HMSFToFrames(dwHmsf, dwFormat);
  91. int fps = (int)FPSDisplay(dwFormat);
  92. dwReturn = ((dwFrames * 1000) + (fps/2)) / fps; // (fps/2) for rounding
  93. return dwReturn;
  94. }
  95. PRIVATE DWORD NEAR PASCAL FramesToHMSF(DWORD dwFrames, DWORD dwFormat)
  96. // convert from frames to hmsf (colonized) format
  97. {
  98. HMSF hmsf;
  99. int fps = (int)FPSDisplay(dwFormat);
  100. hmsf.hours = (BYTE)(dwFrames / ((DWORD) 60 * 60 * fps));
  101. hmsf.minutes = (BYTE)((dwFrames % ((DWORD) 60 * 60 * fps)) / (60 * fps));
  102. hmsf.seconds = (BYTE)((dwFrames % ((DWORD) 60 * fps)) / fps);
  103. hmsf.frames = (BYTE)((dwFrames % fps));
  104. return * ((DWORD FAR *) &hmsf);
  105. }
  106. /**************************** PUBLIC FUNCTIONS *************************/
  107. PUBLIC BOOL NEAR PASCAL ColonizeOutput(pSeqStreamType pStream)
  108. // tells whether the user display type is such that the output should
  109. // displayed colonoized (i.e. "hh:mm:ss:ff")
  110. {
  111. if ((pStream->userDisplayType == MCI_FORMAT_SMPTE_24) ||
  112. (pStream->userDisplayType == MCI_FORMAT_SMPTE_25) ||
  113. (pStream->userDisplayType == MCI_FORMAT_SMPTE_30DROP) ||
  114. (pStream->userDisplayType == MCI_FORMAT_SMPTE_30))
  115. // smpte times are the only colonized formats
  116. return TRUE;
  117. else
  118. return FALSE;
  119. }
  120. PUBLIC BOOL NEAR PASCAL FormatsEqual(pSeqStreamType pStream)
  121. // tells whether the display format is compatible with the file format
  122. // (i.e. will conversion have to be done in interaction with the user)
  123. {
  124. BOOL bReturn;
  125. // Essentially, ppqn file type only compatible with song pointer display;
  126. // SMPTE compatible with anything but ppqn
  127. if (pStream->fileDivType == SEQ_DIV_PPQN)
  128. {
  129. if (pStream->userDisplayType == MCI_SEQ_FORMAT_SONGPTR)
  130. bReturn = TRUE;
  131. else
  132. bReturn = FALSE;
  133. }
  134. else
  135. {
  136. if ((pStream->userDisplayType == MCI_FORMAT_SMPTE_24) ||
  137. (pStream->userDisplayType == MCI_FORMAT_SMPTE_25) ||
  138. (pStream->userDisplayType == MCI_FORMAT_SMPTE_30DROP) ||
  139. (pStream->userDisplayType == MCI_FORMAT_SMPTE_30))
  140. bReturn = TRUE;
  141. else
  142. bReturn = FALSE;
  143. }
  144. return bReturn;
  145. }
  146. PUBLIC DWORD NEAR PASCAL CnvtTimeToSeq(pSeqStreamType pStream, DWORD dwCurrent, MIDISEQINFO FAR * pSeqInfo)
  147. /* The sequencer understands two time units: Ticks for ppqn files,
  148. or frames for smpte files. The user data is presented either as
  149. song pointer, milliseconds, or H(our)M(inute)S(econd)F(rame).
  150. This routine converts FROM user time TO sequencer time.
  151. */
  152. {
  153. DWORD dwMs; // milliseconds
  154. DWORD fps; // frames per second;
  155. DWORD dwReturn;
  156. DWORD dwTicks;
  157. if (FormatsEqual(pStream))
  158. {
  159. if ((pStream->userDisplayType == MCI_FORMAT_SMPTE_24) ||
  160. (pStream->userDisplayType == MCI_FORMAT_SMPTE_25) ||
  161. (pStream->userDisplayType == MCI_FORMAT_SMPTE_30) ||
  162. (pStream->userDisplayType == MCI_FORMAT_SMPTE_30DROP))
  163. // both file and display are smpte
  164. dwReturn = pSeqInfo->wResolution *
  165. HMSFToFrames(dwCurrent, pStream->userDisplayType);
  166. else
  167. //both file and display are ppqn (convert song pointer to ppqn)
  168. dwReturn = (pSeqInfo->wResolution * dwCurrent) / 4;
  169. }
  170. else if (pStream->fileDivType == SEQ_DIV_PPQN)
  171. //ppqn file, display format !ppqn
  172. {
  173. if (pStream->userDisplayType != MCI_FORMAT_MILLISECONDS)
  174. // must be smpte -- convert hmsf to milliseconds
  175. dwMs = HMSFToMS(dwCurrent, pStream->userDisplayType);
  176. else // must be milliseconds already
  177. dwMs = dwCurrent;
  178. // now that we have milliseconds, we must ask the sequencer to
  179. // convert them to ppqn (using it's internal tempo map)
  180. midiSeqMessage((HMIDISEQ) pStream->hSeq, SEQ_MSTOTICKS,
  181. dwMs, (DWORD)(LPSTR) &dwTicks); // passed back in dwTicks
  182. dwReturn = dwTicks;
  183. }
  184. else // smpte file, display format != smpte
  185. {
  186. // NB: don't worry about SONGPTR -- it's illegal here
  187. // also, don't worry about HMSF -- it's equal
  188. // The only possible case is ms -> ticks
  189. fps = FPSFile(pStream->fileDivType);
  190. dwReturn = ((dwCurrent * fps * pSeqInfo->wResolution) + 500) / 1000; // add 500 to round
  191. }
  192. return dwReturn;
  193. }
  194. PUBLIC DWORD NEAR PASCAL CnvtTimeFromSeq(pSeqStreamType pStream, DWORD dwTicks, MIDISEQINFO FAR * pSeqInfo)
  195. // This routine converts FROM sequencer time TO user time.
  196. {
  197. DWORD dwMs; // milliseconds
  198. DWORD fps; // frames per second;
  199. DWORD dwReturn;
  200. DWORD dwFrames;
  201. DWORD dwNativeUnits;
  202. if (pSeqInfo->wDivType == SEQ_DIV_PPQN)
  203. dwNativeUnits = (dwTicks * 4) / pSeqInfo->wResolution;
  204. else
  205. dwNativeUnits = dwTicks / pSeqInfo->wResolution;
  206. if (FormatsEqual(pStream))
  207. {
  208. if ((pStream->userDisplayType == MCI_FORMAT_SMPTE_24) ||
  209. (pStream->userDisplayType == MCI_FORMAT_SMPTE_25) ||
  210. (pStream->userDisplayType == MCI_FORMAT_SMPTE_30) ||
  211. (pStream->userDisplayType == MCI_FORMAT_SMPTE_30DROP))
  212. dwReturn = FramesToHMSF(dwNativeUnits, pStream->userDisplayType);
  213. else
  214. dwReturn = dwNativeUnits; // no conversion needed
  215. }
  216. else if (pStream->fileDivType == SEQ_DIV_PPQN)
  217. {
  218. // convert song ptr to ms
  219. midiSeqMessage((HMIDISEQ) pStream->hSeq, SEQ_TICKSTOMS,
  220. dwTicks, (DWORD)(LPSTR) &dwMs); // passed back in dwSongPtr
  221. if (pStream->userDisplayType == MCI_FORMAT_MILLISECONDS)
  222. dwReturn = dwMs;
  223. else
  224. // convert from ms to frames, and then frames to hmsf format
  225. {
  226. fps = FPSDisplay(pStream->userDisplayType);
  227. dwFrames = (dwMs * fps) / 1000;
  228. dwReturn = FramesToHMSF(dwFrames, pStream->userDisplayType);
  229. }
  230. }
  231. else // smpte file
  232. {
  233. // NB: don't worry about SONGPTR -- it's illegal here
  234. // also, don't worry about HMSF -- it's "equal"
  235. // The only possible case is frames->ms
  236. // set stream display type default based on file div type
  237. fps = FPSFile(pStream->fileDivType);
  238. dwReturn = ((dwTicks * 1000) + (fps/2)) /
  239. (fps * pSeqInfo->wResolution);
  240. // add (fps/2) to round
  241. // BTW: it would take > 39 hours to overflow @ 30fps (23:59:59:29 is max)
  242. }
  243. return dwReturn;
  244. }
  245. PUBLIC BOOL NEAR PASCAL RangeCheck(pSeqStreamType pStream, DWORD dwValue)
  246. /* range checks raw, unconverted data. checks if data is negative, or past
  247. end of file length. also checks if smpte hours, minutes, seconds and frames
  248. are all valid. Returns TRUE if legal, otherwise FALSE */
  249. {
  250. int fps;
  251. HMSF hmsf;
  252. DWORD dwLength;
  253. MIDISEQINFO seqInfo;
  254. // Get length, and convert it to display format
  255. midiSeqMessage((HMIDISEQ) pStream->hSeq,
  256. SEQ_GETINFO, (DWORD) (LPMIDISEQINFO) &seqInfo, 0L);
  257. dwLength = CnvtTimeFromSeq(pStream, seqInfo.dwLength, &seqInfo);
  258. switch (pStream->userDisplayType) // check length based on user format
  259. {
  260. case MCI_FORMAT_SMPTE_24:
  261. case MCI_FORMAT_SMPTE_25:
  262. case MCI_FORMAT_SMPTE_30:
  263. case MCI_FORMAT_SMPTE_30DROP:
  264. hmsf = * ((HMSF FAR *) &dwValue);
  265. fps = (int)FPSDisplay(pStream->userDisplayType); // get frames per second
  266. // check for format errors
  267. if (((int)hmsf.frames >= fps) || (hmsf.seconds >= 60) ||
  268. (hmsf.minutes >= 60) || (hmsf.hours > 24))
  269. return FALSE;
  270. // don't check for negative values, since using unsigned bytes
  271. // (2's comp. negs would get caught above anyway)
  272. // check for length error
  273. if (HMSFToMS(* ((DWORD FAR *) &dwValue), pStream->userDisplayType) >
  274. HMSFToMS(dwLength, pStream->userDisplayType))
  275. return FALSE;
  276. break;
  277. case MCI_SEQ_FORMAT_SONGPTR:
  278. case MCI_FORMAT_MILLISECONDS:
  279. if (dwValue > dwLength)
  280. return FALSE; // past end
  281. }
  282. return TRUE;
  283. }