summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/libflac/src/plugin_winamp2/infobox.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/libflac/src/plugin_winamp2/infobox.c')
-rw-r--r--3rdparty/libflac/src/plugin_winamp2/infobox.c459
1 files changed, 459 insertions, 0 deletions
diff --git a/3rdparty/libflac/src/plugin_winamp2/infobox.c b/3rdparty/libflac/src/plugin_winamp2/infobox.c
new file mode 100644
index 00000000000..00dc5e6fa44
--- /dev/null
+++ b/3rdparty/libflac/src/plugin_winamp2/infobox.c
@@ -0,0 +1,459 @@
+/* in_flac - Winamp2 FLAC input plugin
+ * Copyright (C) 2002,2003,2004,2005,2006,2007 Josh Coalson
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include "FLAC/all.h"
+#include "share/alloc.h"
+#include "plugin_common/all.h"
+#include "infobox.h"
+#include "configure.h"
+#include "resource.h"
+
+
+typedef struct
+{
+ char filename[MAX_PATH];
+ FLAC__StreamMetadata *tags;
+} LOCALDATA;
+
+static char buffer[8192];
+static char *genres = NULL;
+static DWORD genresSize = 0, genresCount = 0;
+static BOOL genresChanged = FALSE, isNT;
+
+static const char infoTitle[] = "FLAC File Info";
+
+/*
+ * Genres
+ */
+
+/* TODO: write genres in utf-8 ? */
+
+static __inline int GetGenresFileName(char *buffer, int size)
+{
+ char *c;
+
+ if (!GetModuleFileName(NULL, buffer, size))
+ return 0;
+ c = strrchr(buffer, '\\');
+ if (!c) return 0;
+ strcpy(c+1, "genres.txt");
+
+ return 1;
+}
+
+static void LoadGenres()
+{
+ HANDLE hFile;
+ DWORD spam;
+ char *c;
+
+ FLAC__ASSERT(0 != genres);
+
+ if (!GetGenresFileName(buffer, sizeof(buffer))) return;
+ /* load file */
+ hFile = CreateFile(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) return;
+ genresSize = GetFileSize(hFile, 0);
+ if (genresSize && (genres = (char*)safe_malloc_add_2op_(genresSize, /*+*/2)))
+ {
+ if (!ReadFile(hFile, genres, genresSize, &spam, NULL) || spam!=genresSize)
+ {
+ free(genres);
+ genres = NULL;
+ }
+ else
+ {
+ genres[genresSize] = 0;
+ genres[genresSize+1] = 0;
+ /* replace newlines */
+ genresChanged = FALSE;
+ genresCount = 1;
+
+ for (c=genres; *c; c++)
+ {
+ if (*c == 10)
+ {
+ *c = 0;
+ if (*(c+1))
+ genresCount++;
+ else genresSize--;
+ }
+ }
+ }
+ }
+
+ CloseHandle(hFile);
+}
+
+static void SaveGenres(HWND hlist)
+{
+ HANDLE hFile;
+ DWORD spam;
+ int i, count, len;
+
+ if (!GetGenresFileName(buffer, sizeof(buffer))) return;
+ /* write file */
+ hFile = CreateFile(buffer, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE) return;
+
+ count = SendMessage(hlist, CB_GETCOUNT, 0, 0);
+ for (i=0; i<count; i++)
+ {
+ SendMessage(hlist, CB_GETLBTEXT, i, (LPARAM)buffer);
+ len = strlen(buffer);
+ if (i != count-1)
+ {
+ buffer[len] = 10;
+ len++;
+ }
+ WriteFile(hFile, buffer, len, &spam, NULL);
+ }
+
+ CloseHandle(hFile);
+}
+
+static void AddGenre(HWND hwnd, const char *genre)
+{
+ HWND hgen = GetDlgItem(hwnd, IDC_GENRE);
+
+ if (SendMessage(hgen, CB_FINDSTRINGEXACT, -1, (LPARAM)genre) == CB_ERR)
+ {
+ genresChanged = TRUE;
+ SendMessage(hgen, CB_ADDSTRING, 0, (LPARAM)genre);
+ }
+}
+
+static void InitGenres(HWND hwnd)
+{
+ HWND hgen = GetDlgItem(hwnd, IDC_GENRE);
+ char *c;
+
+ /* set text length limit to 64 chars */
+ SendMessage(hgen, CB_LIMITTEXT, 64, 0);
+ /* try to load genres */
+ if (!genres)
+ LoadGenres(hgen);
+ /* add the to list */
+ if (genres)
+ {
+ SendMessage(hgen, CB_INITSTORAGE, genresCount, genresSize);
+
+ for (c = genres; *c; c += strlen(c)+1)
+ SendMessage(hgen, CB_ADDSTRING, 0, (LPARAM)c);
+ }
+}
+
+static void DeinitGenres(HWND hwnd, BOOL final)
+{
+ if (genresChanged && hwnd)
+ {
+ SaveGenres(GetDlgItem(hwnd, IDC_GENRE));
+ genresChanged = FALSE;
+ final = TRUE;
+ }
+ if (final)
+ {
+ free(genres);
+ genres = 0;
+ }
+}
+
+static wchar_t *AnsiToWide(const char *src)
+{
+ int len;
+ wchar_t *dest;
+
+ FLAC__ASSERT(0 != src);
+
+ len = strlen(src) + 1;
+ /* copy */
+ dest = (wchar_t*)safe_malloc_mul_2op_(len, /*times*/sizeof(wchar_t));
+ if (dest) mbstowcs(dest, src, len);
+ return dest;
+}
+
+/*
+ * Infobox helpers
+ */
+
+#define SetText(x,y) ucs2 = FLAC_plugin__tags_get_tag_ucs2(data->tags, y); \
+ WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, ucs2, -1, buffer, sizeof(buffer), NULL, NULL); \
+ if(ucs2) free(ucs2); \
+ SetDlgItemText(hwnd, x, buffer)
+
+#define GetText(x,y) GetDlgItemText(hwnd, x, buffer, sizeof(buffer)); \
+ if (*buffer) { ucs2 = AnsiToWide(buffer); FLAC_plugin__tags_set_tag_ucs2(data->tags, y, ucs2, /*replace_all=*/false); free(ucs2); } \
+ else FLAC_plugin__tags_delete_tag(data->tags, y)
+
+#define SetTextW(x,y) ucs2 = FLAC_plugin__tags_get_tag_ucs2(data->tags, y); \
+ SetDlgItemTextW(hwnd, x, ucs2); \
+ free(ucs2)
+
+#define GetTextW(x,y) GetDlgItemTextW(hwnd, x, (WCHAR*)buffer, sizeof(buffer)/2); \
+ if (*(WCHAR*)buffer) FLAC_plugin__tags_set_tag_ucs2(data->tags, y, (WCHAR*)buffer, /*replace_all=*/false); \
+ else FLAC_plugin__tags_delete_tag(data->tags, y)
+
+
+static BOOL InitInfoboxInfo(HWND hwnd, const char *file)
+{
+ LOCALDATA *data = LocalAlloc(LPTR, sizeof(LOCALDATA));
+ wchar_t *ucs2;
+ FLAC__StreamMetadata streaminfo;
+ DWORD length, bps, ratio, rg;
+ LONGLONG filesize;
+
+ SetWindowLong(hwnd, GWL_USERDATA, (LONG)data);
+ /* file name */
+ strncpy(data->filename, file, sizeof(data->filename));
+ SetDlgItemText(hwnd, IDC_NAME, file);
+ /* stream data and vorbis comment */
+ filesize = FileSize(file);
+ if (!filesize) return FALSE;
+ if (!FLAC__metadata_get_streaminfo(file, &streaminfo))
+ return FALSE;
+ ReadTags(file, &data->tags, false);
+
+ length = (DWORD)(streaminfo.data.stream_info.total_samples / streaminfo.data.stream_info.sample_rate);
+ bps = (DWORD)(filesize / (125*streaminfo.data.stream_info.total_samples/streaminfo.data.stream_info.sample_rate));
+ ratio = bps*1000000 / (streaminfo.data.stream_info.sample_rate*streaminfo.data.stream_info.channels*streaminfo.data.stream_info.bits_per_sample);
+ rg = FLAC_plugin__tags_get_tag_utf8(data->tags, "REPLAYGAIN_TRACK_GAIN") ? 1 : 0;
+ rg |= FLAC_plugin__tags_get_tag_utf8(data->tags, "REPLAYGAIN_ALBUM_GAIN") ? 2 : 0;
+
+ sprintf(buffer, "Sample rate: %d Hz\nChannels: %d\nBits per sample: %d\nMin block size: %d\nMax block size: %d\n"
+ "File size: %I64d bytes\nTotal samples: %I64d\nLength: %d:%02d\nAvg. bitrate: %d\nCompression ratio: %d.%d%%\n"
+ "ReplayGain: %s\n",
+ streaminfo.data.stream_info.sample_rate, streaminfo.data.stream_info.channels, streaminfo.data.stream_info.bits_per_sample,
+ streaminfo.data.stream_info.min_blocksize, streaminfo.data.stream_info.max_blocksize, filesize, streaminfo.data.stream_info.total_samples,
+ length/60, length%60, bps, ratio/10, ratio%10,
+ rg==3 ? "track gain\nReplayGain: album gain" : rg==2 ? "album gain" : rg==1 ? "track gain" : "not present");
+
+ SetDlgItemText(hwnd, IDC_INFO, buffer);
+ /* tag */
+ if (isNT)
+ {
+ SetTextW(IDC_TITLE, "TITLE");
+ SetTextW(IDC_ARTIST, "ARTIST");
+ SetTextW(IDC_ALBUM, "ALBUM");
+ SetTextW(IDC_COMMENT, "COMMENT");
+ SetTextW(IDC_YEAR, "DATE");
+ SetTextW(IDC_TRACK, "TRACKNUMBER");
+ SetTextW(IDC_GENRE, "GENRE");
+ }
+ else
+ {
+ SetText(IDC_TITLE, "TITLE");
+ SetText(IDC_ARTIST, "ARTIST");
+ SetText(IDC_ALBUM, "ALBUM");
+ SetText(IDC_COMMENT, "COMMENT");
+ SetText(IDC_YEAR, "DATE");
+ SetText(IDC_TRACK, "TRACKNUMBER");
+ SetText(IDC_GENRE, "GENRE");
+ }
+
+ return TRUE;
+}
+
+static void __inline SetTag(HWND hwnd, const char *filename, FLAC__StreamMetadata *tags)
+{
+ strcpy(buffer, infoTitle);
+
+ if (FLAC_plugin__tags_set(filename, tags))
+ strcat(buffer, " [Updated]");
+ else strcat(buffer, " [Failed]");
+
+ SetWindowText(hwnd, buffer);
+}
+
+static void UpdateTag(HWND hwnd)
+{
+ LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);
+ wchar_t *ucs2;
+
+ /* get fields */
+ if (isNT)
+ {
+ GetTextW(IDC_TITLE, "TITLE");
+ GetTextW(IDC_ARTIST, "ARTIST");
+ GetTextW(IDC_ALBUM, "ALBUM");
+ GetTextW(IDC_COMMENT, "COMMENT");
+ GetTextW(IDC_YEAR, "DATE");
+ GetTextW(IDC_TRACK, "TRACKNUMBER");
+ GetTextW(IDC_GENRE, "GENRE");
+
+ ucs2 = FLAC_plugin__tags_get_tag_ucs2(data->tags, "GENRE");
+ WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, ucs2, -1, buffer, sizeof(buffer), NULL, NULL);
+ free(ucs2);
+ }
+ else
+ {
+ GetText(IDC_TITLE, "TITLE");
+ GetText(IDC_ARTIST, "ARTIST");
+ GetText(IDC_ALBUM, "ALBUM");
+ GetText(IDC_COMMENT, "COMMENT");
+ GetText(IDC_YEAR, "DATE");
+ GetText(IDC_TRACK, "TRACKNUMBER");
+ GetText(IDC_GENRE, "GENRE");
+ }
+
+ /* update genres list (buffer should contain genre) */
+ if (buffer[0]) AddGenre(hwnd, buffer);
+
+ /* write tag */
+ SetTag(hwnd, data->filename, data->tags);
+}
+
+static void RemoveTag(HWND hwnd)
+{
+ LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);
+ FLAC_plugin__tags_delete_all(data->tags);
+
+ SetDlgItemText(hwnd, IDC_TITLE, "");
+ SetDlgItemText(hwnd, IDC_ARTIST, "");
+ SetDlgItemText(hwnd, IDC_ALBUM, "");
+ SetDlgItemText(hwnd, IDC_COMMENT, "");
+ SetDlgItemText(hwnd, IDC_YEAR, "");
+ SetDlgItemText(hwnd, IDC_TRACK, "");
+ SetDlgItemText(hwnd, IDC_GENRE, "");
+
+ SetTag(hwnd, data->filename, data->tags);
+}
+
+
+static INT_PTR CALLBACK InfoProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ /* init */
+ case WM_INITDIALOG:
+ SetWindowText(hwnd, infoTitle);
+ InitGenres(hwnd);
+ /* init fields */
+ if (!InitInfoboxInfo(hwnd, (const char*)lParam))
+ PostMessage(hwnd, WM_CLOSE, 0, 0);
+ return TRUE;
+ /* destroy */
+ case WM_DESTROY:
+ {
+ LOCALDATA *data = (LOCALDATA*)GetWindowLong(hwnd, GWL_USERDATA);
+ FLAC_plugin__tags_destroy(&data->tags);
+ LocalFree(data);
+ DeinitGenres(hwnd, FALSE);
+ }
+ break;
+ /* commands */
+ case WM_COMMAND:
+ switch (LOWORD(wParam))
+ {
+ /* ok/cancel */
+ case IDOK:
+ case IDCANCEL:
+ EndDialog(hwnd, LOWORD(wParam));
+ return TRUE;
+ /* save */
+ case IDC_UPDATE:
+ UpdateTag(hwnd);
+ break;
+ /* remove */
+ case IDC_REMOVE:
+ RemoveTag(hwnd);
+ break;
+ }
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Helpers
+ */
+
+ULONGLONG FileSize(const char *fileName)
+{
+ LARGE_INTEGER res;
+ HANDLE hFile = CreateFile(fileName, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (hFile == INVALID_HANDLE_VALUE) return 0;
+ res.LowPart = GetFileSize(hFile, &res.HighPart);
+ CloseHandle(hFile);
+ return res.QuadPart;
+}
+
+static __inline char *GetFileName(const char *fullname)
+{
+ const char *c = fullname + strlen(fullname) - 1;
+
+ while (c > fullname)
+ {
+ if (*c=='\\' || *c=='/')
+ {
+ c++;
+ break;
+ }
+ c--;
+ }
+
+ return (char*)c;
+}
+
+void ReadTags(const char *fileName, FLAC__StreamMetadata **tags, BOOL forDisplay)
+{
+ if(FLAC_plugin__tags_get(fileName, tags)) {
+
+ /* add file name */
+ if (forDisplay)
+ {
+ char *c;
+ wchar_t *ucs2;
+ ucs2 = AnsiToWide(fileName);
+ FLAC_plugin__tags_set_tag_ucs2(*tags, "filepath", ucs2, /*replace_all=*/true);
+ free(ucs2);
+
+ strcpy(buffer, GetFileName(fileName));
+ if (c = strrchr(buffer, '.')) *c = 0;
+ ucs2 = AnsiToWide(buffer);
+ FLAC_plugin__tags_set_tag_ucs2(*tags, "filename", ucs2, /*replace_all=*/true);
+ free(ucs2);
+ }
+ }
+}
+
+/*
+ * Front-end
+ */
+
+void InitInfobox()
+{
+ isNT = !(GetVersion() & 0x80000000);
+}
+
+void DeinitInfobox()
+{
+ DeinitGenres(NULL, true);
+}
+
+void DoInfoBox(HINSTANCE inst, HWND hwnd, const char *filename)
+{
+ DialogBoxParam(inst, MAKEINTRESOURCE(IDD_INFOBOX), hwnd, InfoProc, (LONG)filename);
+}