PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Chap22/Drum/DrumFile.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 276 lines | 201 code | 53 blank | 22 comment | 29 complexity | d4cd02b2a226da0c7dbf520d21e5ee7e MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module DrumFile;
  6. import core.memory;
  7. import core.runtime;
  8. import core.thread;
  9. import std.algorithm : min, max;
  10. import std.conv;
  11. import std.math;
  12. import std.range;
  13. import std.string;
  14. import std.utf : count, toUTFz;
  15. auto toUTF16z(S)(S s)
  16. {
  17. return toUTFz!(const(wchar)*)(s);
  18. }
  19. pragma(lib, "gdi32.lib");
  20. pragma(lib, "comdlg32.lib");
  21. pragma(lib, "winmm.lib");
  22. import core.sys.windows.windef;
  23. import core.sys.windows.winuser;
  24. import core.sys.windows.wingdi;
  25. import core.sys.windows.winbase;
  26. import core.sys.windows.commdlg;
  27. import core.sys.windows.mmsystem;
  28. import DrumTime;
  29. OPENFILENAME ofn;
  30. // The API expects these to be arrays of pointers.
  31. const TCHAR*[3] szFilter =
  32. [
  33. "Drum Files (*.DRM)\0"w.ptr,
  34. "*.drm\0"w.ptr,
  35. "\0"w.ptr
  36. ];
  37. wchar* szDrumID;
  38. wchar* szListID;
  39. wchar* szInfoID;
  40. wchar* szSoftID;
  41. wchar* szDateID;
  42. wchar* szFmtID;
  43. wchar* szDataID;
  44. char* szSoftware;
  45. wchar* szErrorNoCreate;
  46. wchar* szErrorCannotWrite;
  47. wchar* szErrorNotFound;
  48. wchar* szErrorNotDrum;
  49. wchar* szErrorUnsupported;
  50. wchar* szErrorCannotRead;
  51. static this()
  52. {
  53. szDrumID = cast(wchar*)"DRUM".toUTF16z;
  54. szListID = cast(wchar*)"LIST".toUTF16z;
  55. szInfoID = cast(wchar*)"INFO".toUTF16z;
  56. szSoftID = cast(wchar*)"ISFT".toUTF16z;
  57. szDateID = cast(wchar*)"ISCD".toUTF16z;
  58. szFmtID = cast(wchar*)"fmt ".toUTF16z;
  59. szDataID = cast(wchar*)"data".toUTF16z;
  60. szSoftware = cast(char*)"DRUM by Charles Petzold, Programming Windows".toStringz;
  61. szErrorNoCreate = cast(wchar*)"File %s could not be opened for writing.".toUTF16z;
  62. szErrorCannotWrite = cast(wchar*)"File %s could not be written to.".toUTF16z;
  63. szErrorNotFound = cast(wchar*)"File %s not found or cannot be opened.".toUTF16z;
  64. szErrorNotDrum = cast(wchar*)"File %s is not a standard DRUM file.".toUTF16z;
  65. szErrorUnsupported = cast(wchar*)"File %s is not a supported DRUM file.".toUTF16z;
  66. szErrorCannotRead = cast(wchar*)"File %s cannot be read.".toUTF16z;
  67. }
  68. BOOL DrumFileOpenDlg(HWND hwnd, wchar* szFileName, wchar* szTitleName)
  69. {
  70. ofn.hwndOwner = hwnd;
  71. ofn.lpstrFilter = szFilter[0];
  72. ofn.lpstrFile = szFileName;
  73. ofn.nMaxFile = MAX_PATH;
  74. ofn.lpstrFileTitle = szTitleName;
  75. ofn.nMaxFileTitle = MAX_PATH;
  76. ofn.Flags = OFN_CREATEPROMPT;
  77. ofn.lpstrDefExt = "drm".toUTF16z;
  78. return GetOpenFileName(&ofn);
  79. }
  80. BOOL DrumFileSaveDlg(HWND hwnd, TCHAR* szFileName, TCHAR* szTitleName)
  81. {
  82. ofn.hwndOwner = hwnd;
  83. ofn.lpstrFilter = szFilter[0];
  84. ofn.lpstrFile = szFileName;
  85. ofn.nMaxFile = MAX_PATH;
  86. ofn.lpstrFileTitle = szTitleName;
  87. ofn.nMaxFileTitle = MAX_PATH;
  88. ofn.Flags = OFN_OVERWRITEPROMPT;
  89. ofn.lpstrDefExt = "drm".toUTF16z;
  90. return GetSaveFileName(&ofn);
  91. }
  92. wstring fromWStringz(const wchar* s)
  93. {
  94. if (s is null) return null;
  95. wchar* ptr;
  96. for (ptr = cast(wchar*)s; *ptr; ++ptr) {}
  97. return to!wstring(s[0..ptr-s]);
  98. }
  99. TCHAR* DrumFileWrite(DRUM* pdrum, TCHAR* szFileName)
  100. {
  101. // replace wError |= with enforce, and do scope(failure).
  102. string szDateBuf;
  103. HMMIO hmmio;
  104. int iFormat = 2;
  105. MMCKINFO[3] mmckinfo;
  106. SYSTEMTIME st;
  107. WORD wError = 0;
  108. // Recreate the file for writing
  109. hmmio = mmioOpen(szFileName, NULL, MMIO_CREATE | MMIO_WRITE | MMIO_ALLOCBUF);
  110. if (hmmio == NULL)
  111. return szErrorNoCreate;
  112. // Create a "RIFF" chunk with a "CPDR" type
  113. mmckinfo[0].fccType = mmioStringToFOURCC(szDrumID, 0);
  114. wError |= mmioCreateChunk(hmmio, &mmckinfo[0], MMIO_CREATERIFF);
  115. // Create "LIST" sub-chunk with an "INFO" type
  116. mmckinfo[1].fccType = mmioStringToFOURCC(szInfoID, 0);
  117. wError |= mmioCreateChunk(hmmio, &mmckinfo[1], MMIO_CREATELIST);
  118. // Create "ISFT" sub-sub-chunk
  119. mmckinfo[2].ckid = mmioStringToFOURCC(szSoftID, 0);
  120. wError |= mmioCreateChunk(hmmio, &mmckinfo[2], 0);
  121. wError |= (mmioWrite(hmmio, szSoftware, szSoftware.sizeof) != szSoftware.sizeof);
  122. wError |= mmioAscend(hmmio, &mmckinfo[2], 0);
  123. GetLocalTime(&st);
  124. szDateBuf = format("%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
  125. // Create "ISCD" sub-sub-chunk
  126. mmckinfo[2].ckid = mmioStringToFOURCC(szDateID, 0);
  127. wError |= mmioCreateChunk(hmmio, &mmckinfo[2], 0);
  128. wError |= (mmioWrite(hmmio, szDateBuf.toStringz, szDateBuf.count) != cast(int)(szDateBuf.count));
  129. wError |= mmioAscend(hmmio, &mmckinfo[2], 0);
  130. wError |= mmioAscend(hmmio, &mmckinfo[1], 0);
  131. // Create "fmt " sub-chunk
  132. mmckinfo[1].ckid = mmioStringToFOURCC(szFmtID, 0);
  133. wError |= mmioCreateChunk(hmmio, &mmckinfo[1], 0);
  134. wError |= (mmioWrite(hmmio, cast(PSTR)&iFormat, int.sizeof) != int.sizeof);
  135. wError |= mmioAscend(hmmio, &mmckinfo[1], 0);
  136. // Create the "data" sub-chunk
  137. mmckinfo[1].ckid = mmioStringToFOURCC(szDataID, 0);
  138. wError |= mmioCreateChunk(hmmio, &mmckinfo[1], 0);
  139. wError |= (mmioWrite(hmmio, cast(PSTR)pdrum, DRUM.sizeof) != DRUM.sizeof);
  140. wError |= mmioAscend(hmmio, &mmckinfo[1], 0);
  141. wError |= mmioAscend(hmmio, &mmckinfo[0], 0);
  142. // Clean up and return
  143. wError |= mmioClose(hmmio, 0);
  144. if (wError)
  145. {
  146. mmioOpen(szFileName, NULL, MMIO_DELETE);
  147. return szErrorCannotWrite;
  148. }
  149. return NULL;
  150. }
  151. TCHAR* DrumFileRead(DRUM* pdrum, TCHAR* szFileName)
  152. {
  153. DRUM drum;
  154. HMMIO hmmio;
  155. int i, iFormat;
  156. MMCKINFO[3] mmckinfo;
  157. // Open the file
  158. hmmio = mmioOpen(szFileName, NULL, MMIO_READ);
  159. if (hmmio == NULL)
  160. return szErrorNotFound;
  161. // Locate a "RIFF" chunk with a "DRUM" form-type
  162. mmckinfo[0].ckid = mmioStringToFOURCC(szDrumID, 0);
  163. if (mmioDescend(hmmio, &mmckinfo[0], NULL, MMIO_FINDRIFF))
  164. {
  165. mmioClose(hmmio, 0);
  166. return szErrorNotDrum;
  167. }
  168. // Locate, read, and verify the "fmt " sub-chunk
  169. mmckinfo[1].ckid = mmioStringToFOURCC(szFmtID, 0);
  170. if (mmioDescend(hmmio, &mmckinfo[1], &mmckinfo[0], MMIO_FINDCHUNK))
  171. {
  172. mmioClose(hmmio, 0);
  173. return szErrorNotDrum;
  174. }
  175. if (mmckinfo[1].cksize != int.sizeof)
  176. {
  177. mmioClose(hmmio, 0);
  178. return szErrorUnsupported;
  179. }
  180. if (mmioRead(hmmio, cast(PSTR)&iFormat, int.sizeof) != int.sizeof)
  181. {
  182. mmioClose(hmmio, 0);
  183. return szErrorCannotRead;
  184. }
  185. if (iFormat != 1 && iFormat != 2)
  186. {
  187. mmioClose(hmmio, 0);
  188. return szErrorUnsupported;
  189. }
  190. // Go to end of "fmt " sub-chunk
  191. mmioAscend(hmmio, &mmckinfo[1], 0);
  192. // Locate, read, and verify the "data" sub-chunk
  193. mmckinfo[1].ckid = mmioStringToFOURCC(szDataID, 0);
  194. //~ writeln((cast(char*)&mmckinfo[1].ckid)[0..4]);
  195. if (mmioDescend(hmmio, &mmckinfo[1], &mmckinfo[0], MMIO_FINDCHUNK))
  196. {
  197. mmioClose(hmmio, 0);
  198. return szErrorNotDrum;
  199. }
  200. if (mmckinfo[1].cksize != DRUM.sizeof)
  201. {
  202. mmioClose(hmmio, 0);
  203. return szErrorUnsupported;
  204. }
  205. if (mmioRead(hmmio, cast(LPSTR)&drum, DRUM.sizeof) != DRUM.sizeof)
  206. {
  207. mmioClose(hmmio, 0);
  208. return szErrorCannotRead;
  209. }
  210. // Close the file
  211. mmioClose(hmmio, 0);
  212. // Convert format 1 to format 2 and copy the DRUM structure data
  213. if (iFormat == 1)
  214. {
  215. for (i = 0; i < NUM_PERC; i++)
  216. {
  217. drum.dwSeqPerc [i] = drum.dwSeqPian [i];
  218. drum.dwSeqPian [i] = 0;
  219. }
  220. }
  221. *pdrum = drum;
  222. return NULL;
  223. }