infobox.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:12k
源码类别:

Windows CE

开发平台:

C/C++

  1. /* in_flac - Winamp2 FLAC input plugin
  2.  * Copyright (C) 2002,2003,2004,2005  Josh Coalson
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include "FLAC/all.h"
  21. #include "plugin_common/all.h"
  22. #include "infobox.h"
  23. #include "config.h"
  24. #include "resource.h"
  25. typedef struct
  26. {
  27. char filename[MAX_PATH];
  28. FLAC__StreamMetadata *tags;
  29. } LOCALDATA;
  30. static char buffer[8192];
  31. static char *genres = NULL;
  32. static DWORD genresSize = 0, genresCount = 0;
  33. static BOOL genresChanged = FALSE, isNT;
  34. static const char infoTitle[] = "FLAC File Info";
  35. /*
  36.  *  Genres
  37.  */
  38. /* TODO: write genres in utf-8 ? */
  39. static __inline int GetGenresFileName(char *buffer, int size)
  40. {
  41. char *c;
  42. if (!GetModuleFileName(NULL, buffer, size))
  43. return 0;
  44. c = strrchr(buffer, '\');
  45. if (!c) return 0;
  46. strcpy(c+1, "genres.txt");
  47. return 1;
  48. }
  49. static void LoadGenres()
  50. {
  51. HANDLE hFile;
  52. DWORD  spam;
  53. char  *c;
  54. FLAC__ASSERT(0 != genres);
  55. if (!GetGenresFileName(buffer, sizeof(buffer))) return;
  56. /* load file */
  57. hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  58. if (hFile == INVALID_HANDLE_VALUE) return;
  59. genresSize = GetFileSize(hFile, 0);
  60. if (genresSize && (genres = (char*)malloc(genresSize+2)))
  61. {
  62. if (!ReadFile(hFile, genres, genresSize, &spam, NULL) || spam!=genresSize)
  63. {
  64. free(genres);
  65. genres = NULL;
  66. }
  67. else
  68. {
  69. genres[genresSize] = 0;
  70. genres[genresSize+1] = 0;
  71. /* replace newlines */
  72. genresChanged = FALSE;
  73. genresCount = 1;
  74. for (c=genres; *c; c++)
  75. {
  76. if (*c == 10)
  77. {
  78. *c = 0;
  79. if (*(c+1))
  80. genresCount++;
  81. else genresSize--;
  82. }
  83. }
  84. }
  85. }
  86. CloseHandle(hFile);
  87. }
  88. static void SaveGenres(HWND hlist)
  89. {
  90. HANDLE hFile;
  91. DWORD  spam;
  92. int i, count, len;
  93. if (!GetGenresFileName(buffer, sizeof(buffer))) return;
  94. /* write file */
  95. hFile = CreateFile(buffer, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  96. if (hFile == INVALID_HANDLE_VALUE) return;
  97. count = SendMessage(hlist, CB_GETCOUNT, 0, 0);
  98. for (i=0; i<count; i++)
  99. {
  100. SendMessage(hlist, CB_GETLBTEXT, i, (LPARAM)buffer);
  101. len = strlen(buffer);
  102. if (i != count-1)
  103. {
  104. buffer[len] = 10;
  105. len++;
  106. }
  107. WriteFile(hFile, buffer, len, &spam, NULL);
  108. }
  109. CloseHandle(hFile);
  110. }
  111. static void AddGenre(HWND hwnd, const char *genre)
  112. {
  113. HWND hgen = GetDlgItem(hwnd, IDC_GENRE);
  114. if (SendMessage(hgen, CB_FINDSTRINGEXACT, -1, (LPARAM)genre) == CB_ERR)
  115. {
  116. genresChanged = TRUE;
  117. SendMessage(hgen, CB_ADDSTRING, 0, (LPARAM)genre);
  118. }
  119. }
  120. static void InitGenres(HWND hwnd)
  121. {
  122. HWND hgen = GetDlgItem(hwnd, IDC_GENRE);
  123. char *c;
  124. /* set text length limit to 64 chars */
  125. SendMessage(hgen, CB_LIMITTEXT, 64, 0);
  126. /* try to load genres */
  127. if (!genres)
  128. LoadGenres(hgen);
  129. /* add the to list */
  130. if (genres)
  131. {
  132. SendMessage(hgen, CB_INITSTORAGE, genresCount, genresSize);
  133. for (c = genres; *c; c += strlen(c)+1)
  134. SendMessage(hgen, CB_ADDSTRING, 0, (LPARAM)c);
  135. }
  136. }
  137. static void DeinitGenres(HWND hwnd, BOOL final)
  138. {
  139. if (genresChanged && hwnd)
  140. {
  141. SaveGenres(GetDlgItem(hwnd, IDC_GENRE));
  142. genresChanged = FALSE;
  143. final = TRUE;
  144. }
  145. if (final)
  146. {
  147. free(genres);
  148. genres = 0;
  149. }
  150. }
  151. static wchar_t *AnsiToWide(const char *src)
  152. {
  153. int len;
  154. wchar_t *dest;
  155. FLAC__ASSERT(0 != src);
  156. len = strlen(src) + 1;
  157. /* copy */
  158. dest = (wchar_t*)malloc(len*sizeof(wchar_t));
  159. if (dest) mbstowcs(dest, src, len);
  160. return dest;
  161. }
  162. /*
  163.  *  Infobox helpers
  164.  */
  165. #define SetText(x,y)            ucs2 = FLAC_plugin__tags_get_tag_ucs2(data->tags, y); 
  166.                                 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, ucs2, -1, buffer, sizeof(buffer), NULL, NULL); 
  167.                                 if(ucs2) free(ucs2); 
  168.                                 SetDlgItemText(hwnd, x, buffer)
  169. #define GetText(x,y)            GetDlgItemText(hwnd, x, buffer, sizeof(buffer));                        
  170.                                 if (*buffer) { ucs2 = AnsiToWide(buffer); FLAC_plugin__tags_set_tag_ucs2(data->tags, y, ucs2, /*replace_all=*/false); free(ucs2); } 
  171.                                 else FLAC_plugin__tags_delete_tag(data->tags, y)
  172. #define SetTextW(x,y)           ucs2 = FLAC_plugin__tags_get_tag_ucs2(data->tags, y); 
  173.                                 SetDlgItemTextW(hwnd, x, ucs2); 
  174.                                 free(ucs2)
  175. #define GetTextW(x,y)           GetDlgItemTextW(hwnd, x, (WCHAR*)buffer, sizeof(buffer)/2);                     
  176.                                 if (*(WCHAR*)buffer) FLAC_plugin__tags_set_tag_ucs2(data->tags, y, (WCHAR*)buffer, /*replace_all=*/false); 
  177.                                 else FLAC_plugin__tags_delete_tag(data->tags, y)
  178. static BOOL InitInfoboxInfo(HWND hwnd, const char *file)
  179. {
  180. LOCALDATA *data = LocalAlloc(LPTR, sizeof(LOCALDATA));
  181. wchar_t *ucs2;
  182. FLAC__StreamMetadata streaminfo;
  183. DWORD    length, bps, ratio, rg;
  184. LONGLONG filesize;
  185. SetWindowLong(hwnd, GWL_USERDATA, (LONG)data);
  186. /* file name */
  187. strncpy(data->filename, file, sizeof(data->filename));
  188. SetDlgItemText(hwnd, IDC_NAME, file);
  189. /* stream data and vorbis comment */
  190. filesize = FileSize(file);
  191. if (!filesize) return FALSE;
  192. if (!FLAC__metadata_get_streaminfo(file, &streaminfo))
  193. return FALSE;
  194. ReadTags(file, &data->tags, false);
  195. length = (DWORD)(streaminfo.data.stream_info.total_samples / streaminfo.data.stream_info.sample_rate);
  196. bps = (DWORD)(filesize / (125*streaminfo.data.stream_info.total_samples/streaminfo.data.stream_info.sample_rate));
  197. ratio = bps*1000000 / (streaminfo.data.stream_info.sample_rate*streaminfo.data.stream_info.channels*streaminfo.data.stream_info.bits_per_sample);
  198. rg  = FLAC_plugin__tags_get_tag_utf8(data->tags, "REPLAYGAIN_TRACK_GAIN") ? 1 : 0;
  199. rg |= FLAC_plugin__tags_get_tag_utf8(data->tags, "REPLAYGAIN_ALBUM_GAIN") ? 2 : 0;
  200. sprintf(buffer, "Sample rate: %d HznChannels: %dnBits per sample: %dnMin block size: %dnMax block size: %dn"
  201.                 "File size: %I64d bytesnTotal samples: %I64dnLength: %d:%02dnAvg. bitrate: %dnCompression ratio: %d.%d%%n"
  202.                 "ReplayGain: %sn",
  203.     streaminfo.data.stream_info.sample_rate, streaminfo.data.stream_info.channels, streaminfo.data.stream_info.bits_per_sample,
  204.     streaminfo.data.stream_info.min_blocksize, streaminfo.data.stream_info.max_blocksize, filesize, streaminfo.data.stream_info.total_samples,
  205.     length/60, length%60, bps, ratio/10, ratio%10,
  206.     rg==3 ? "track gainnReplayGain: album gain" : rg==2 ? "album gain" : rg==1 ? "track gain" : "not present");
  207. SetDlgItemText(hwnd, IDC_INFO, buffer);
  208. /* tag */
  209. if (isNT)
  210. {
  211. SetTextW(IDC_TITLE,   "TITLE");
  212. SetTextW(IDC_ARTIST,  "ARTIST");
  213. SetTextW(IDC_ALBUM,   "ALBUM");
  214. SetTextW(IDC_COMMENT, "COMMENT");
  215. SetTextW(IDC_YEAR,    "DATE");
  216. SetTextW(IDC_TRACK,   "TRACKNUMBER");
  217. SetTextW(IDC_GENRE,   "GENRE");
  218. }
  219. else
  220. {
  221. SetText(IDC_TITLE,   "TITLE");
  222. SetText(IDC_ARTIST,  "ARTIST");
  223. SetText(IDC_ALBUM,   "ALBUM");
  224. SetText(IDC_COMMENT, "COMMENT");
  225. SetText(IDC_YEAR,    "DATE");
  226. SetText(IDC_TRACK,   "TRACKNUMBER");
  227. SetText(IDC_GENRE,   "GENRE");
  228. }
  229. return TRUE;
  230. }
  231. static void __inline SetTag(HWND hwnd, const char *filename, FLAC__StreamMetadata *tags)
  232. {
  233. strcpy(buffer, infoTitle);
  234. if (FLAC_plugin__tags_set(filename, tags))
  235. strcat(buffer, " [Updated]");
  236. else strcat(buffer, " [Failed]");
  237. SetWindowText(hwnd, buffer);
  238. }
  239. static void UpdateTag(HWND hwnd)
  240. {
  241. LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);
  242. wchar_t *ucs2;
  243. /* get fields */
  244. if (isNT)
  245. {
  246. GetTextW(IDC_TITLE,   "TITLE");
  247. GetTextW(IDC_ARTIST,  "ARTIST");
  248. GetTextW(IDC_ALBUM,   "ALBUM");
  249. GetTextW(IDC_COMMENT, "COMMENT");
  250. GetTextW(IDC_YEAR,    "DATE");
  251. GetTextW(IDC_TRACK,   "TRACKNUMBER");
  252. GetTextW(IDC_GENRE,   "GENRE");
  253. ucs2 = FLAC_plugin__tags_get_tag_ucs2(data->tags, "GENRE");
  254. WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, ucs2, -1, buffer, sizeof(buffer), NULL, NULL);
  255. free(ucs2);
  256. }
  257. else
  258. {
  259. GetText(IDC_TITLE,   "TITLE");
  260. GetText(IDC_ARTIST,  "ARTIST");
  261. GetText(IDC_ALBUM,   "ALBUM");
  262. GetText(IDC_COMMENT, "COMMENT");
  263. GetText(IDC_YEAR,    "DATE");
  264. GetText(IDC_TRACK,   "TRACKNUMBER");
  265. GetText(IDC_GENRE,   "GENRE");
  266. }
  267. /* update genres list (buffer should contain genre) */
  268. if (buffer[0]) AddGenre(hwnd, buffer);
  269. /* write tag */
  270. SetTag(hwnd, data->filename, data->tags);
  271. }
  272. static void RemoveTag(HWND hwnd)
  273. {
  274. LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);
  275. FLAC_plugin__tags_delete_all(data->tags);
  276. SetDlgItemText(hwnd, IDC_TITLE,   "");
  277. SetDlgItemText(hwnd, IDC_ARTIST,  "");
  278. SetDlgItemText(hwnd, IDC_ALBUM,   "");
  279. SetDlgItemText(hwnd, IDC_COMMENT, "");
  280. SetDlgItemText(hwnd, IDC_YEAR,    "");
  281. SetDlgItemText(hwnd, IDC_TRACK,   "");
  282. SetDlgItemText(hwnd, IDC_GENRE,   "");
  283. SetTag(hwnd, data->filename, data->tags);
  284. }
  285. static INT_PTR CALLBACK InfoProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  286. {
  287. switch (msg)
  288. {
  289. /* init */
  290. case WM_INITDIALOG:
  291. SetWindowText(hwnd, infoTitle);
  292. InitGenres(hwnd);
  293. /* init fields */
  294. if (!InitInfoboxInfo(hwnd, (const char*)lParam))
  295. PostMessage(hwnd, WM_CLOSE, 0, 0);
  296. return TRUE;
  297. /* destroy */
  298. case WM_DESTROY:
  299. {
  300. LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);
  301. FLAC_plugin__tags_destroy(&data->tags);
  302. LocalFree(data);
  303. DeinitGenres(hwnd, FALSE);
  304. }
  305. break;
  306. /* commands */
  307. case WM_COMMAND:
  308. switch (LOWORD(wParam))
  309. {
  310. /* ok/cancel */
  311. case IDOK:
  312. case IDCANCEL:
  313. EndDialog(hwnd, LOWORD(wParam));
  314. return TRUE;
  315. /* save */
  316. case IDC_UPDATE:
  317. UpdateTag(hwnd);
  318. break;
  319. /* remove */
  320. case IDC_REMOVE:
  321. RemoveTag(hwnd);
  322. break;
  323. }
  324. break;
  325. }
  326. return 0;
  327. }
  328. /*
  329.  *  Helpers
  330.  */
  331. ULONGLONG FileSize(const char *fileName)
  332. {
  333. LARGE_INTEGER res;
  334. HANDLE hFile = CreateFile(fileName, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  335. if (hFile == INVALID_HANDLE_VALUE) return 0;
  336. res.LowPart = GetFileSize(hFile, &res.HighPart);
  337. CloseHandle(hFile);
  338. return res.QuadPart;
  339. }
  340. static __inline char *GetFileName(const char *fullname)
  341. {
  342. const char *c = fullname + strlen(fullname) - 1;
  343. while (c > fullname)
  344. {
  345. if (*c=='\' || *c=='/')
  346. {
  347. c++;
  348. break;
  349. }
  350. c--;
  351. }
  352. return (char*)c;
  353. }
  354. void ReadTags(const char *fileName, FLAC__StreamMetadata **tags, BOOL forDisplay)
  355. {
  356. if(FLAC_plugin__tags_get(fileName, tags)) {
  357. /* add file name */
  358. if (forDisplay)
  359. {
  360. char *c;
  361. wchar_t *ucs2;
  362. ucs2 = AnsiToWide(fileName);
  363. FLAC_plugin__tags_set_tag_ucs2(*tags, "filepath", ucs2, /*replace_all=*/true);
  364. free(ucs2);
  365. strcpy(buffer, GetFileName(fileName));
  366. if (c = strrchr(buffer, '.')) *c = 0;
  367. ucs2 = AnsiToWide(buffer);
  368. FLAC_plugin__tags_set_tag_ucs2(*tags, "filename", ucs2, /*replace_all=*/true);
  369. free(ucs2);
  370. }
  371. }
  372. }
  373. /*
  374.  *  Front-end
  375.  */
  376. void InitInfobox()
  377. {
  378. isNT = !(GetVersion() & 0x80000000);
  379. }
  380. void DeinitInfobox()
  381. {
  382. DeinitGenres(NULL, true);
  383. }
  384. void DoInfoBox(HINSTANCE inst, HWND hwnd, const char *filename)
  385. {
  386. DialogBoxParam(inst, MAKEINTRESOURCE(IDD_INFOBOX), hwnd, InfoProc, (LONG)filename);
  387. }