diff options
Diffstat (limited to 'Src/Plugins/Input/in_mp3/ExtendedInfo.cpp')
-rw-r--r-- | Src/Plugins/Input/in_mp3/ExtendedInfo.cpp | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/Src/Plugins/Input/in_mp3/ExtendedInfo.cpp b/Src/Plugins/Input/in_mp3/ExtendedInfo.cpp new file mode 100644 index 00000000..a3affdeb --- /dev/null +++ b/Src/Plugins/Input/in_mp3/ExtendedInfo.cpp @@ -0,0 +1,315 @@ +#include "main.h" +#include "Metadata.h" +#include "../Winamp/wa_ipc.h" +#include "../nu/ns_wc.h" +#include "uvox_3901.h" +#include "uvox_3902.h" +#include "Stopper.h" +#include <shlwapi.h> +#include "../Agave/Language/api_language.h" +#include <strsafe.h> + +extern CGioFile *g_playing_file; +static FILETIME ftLastWriteTime; + +// is used to determine if the last write time of the file has changed when +// asked to get the metadata for the same cached file so we can update things +BOOL HasFileTimeChanged(const wchar_t *fn) +{ + WIN32_FILE_ATTRIBUTE_DATA fileData = {0}; + if (GetFileAttributesExW(fn, GetFileExInfoStandard, &fileData) == TRUE) + { + if(CompareFileTime(&ftLastWriteTime, &fileData.ftLastWriteTime)) + { + ftLastWriteTime = fileData.ftLastWriteTime; + return TRUE; + } + } + return FALSE; +} + +void UpdateFileTimeChanged(const wchar_t *fn) +{ + WIN32_FILE_ATTRIBUTE_DATA fileData; + if (GetFileAttributesExW(fn, GetFileExInfoStandard, &fileData) == TRUE) + { + ftLastWriteTime = fileData.ftLastWriteTime; + } +} + +Metadata *m_ext_set_mp3info = NULL; +Metadata *m_ext_get_mp3info = NULL; +extern "C" __declspec(dllexport) +int winampGetExtendedFileInfoW(const wchar_t *fn, const char *data, wchar_t *dest, size_t destlen) +{ + if (!_stricmp(data, "type")) + { + dest[0] = '0'; + dest[1] = 0; + return 1; + } + if (!_stricmp(data, "rateable")) + { + dest[0] = '1'; + dest[1] = 0; + return 1; + } + else if (!_stricmp(data, "family")) + { + if (!fn || !fn[0]) return 0; + int len = lstrlenW(fn); + if (len < 4 || L'.' != fn[len - 4]) return 0; + const wchar_t *p = &fn[len - 3]; + if (!_wcsicmp(p, L"MP3")) { WASABI_API_LNGSTRINGW_BUF(IDS_FAMILY_STRING_MP3, dest, destlen); return 1; } + if (!_wcsicmp(p, L"MP2")) { WASABI_API_LNGSTRINGW_BUF(IDS_FAMILY_STRING_MP2, dest, destlen); return 1; } + if (!_wcsicmp(p, L"MP1")) { WASABI_API_LNGSTRINGW_BUF(IDS_FAMILY_STRING_MP1, dest, destlen); return 1; } + if (!_wcsicmp(p, L"AAC")) { WASABI_API_LNGSTRINGW_BUF(IDS_FAMILY_STRING_MPEG2_AAC, dest, destlen); return 1; } + if (!_wcsicmp(p, L"VLB")) { WASABI_API_LNGSTRINGW_BUF(IDS_FAMILY_STRING_DOLBY, dest, destlen); return 1; } + return 0; + } + else if (!_stricmp(data, "mime")) + { + if (!fn || !fn[0]) return 0; + int len = lstrlenW(fn); + if (len < 4 || L'.' != fn[len - 4]) return 0; + const wchar_t *p = &fn[len - 3]; + if (!_wcsicmp(p, L"MP3")) { StringCchCopyW(dest, destlen, L"audio/mpeg"); return 1; } + if (!_wcsicmp(p, L"MP2")) { StringCchCopyW(dest, destlen, L"audio/mpeg"); return 1; } + if (!_wcsicmp(p, L"MP1")) { StringCchCopyW(dest, destlen, L"audio/mpeg"); return 1; } + if (!_wcsicmp(p, L"AAC")) { StringCchCopyW(dest, destlen, L"audio/aac"); return 1; } + if (!_wcsicmp(p, L"VLB")) { StringCchCopyW(dest, destlen, L"audio/vlb"); return 1; } + return 0; + } + else if (!_strnicmp(data, "uvox/", 5)) + { + EnterCriticalSection(&streamInfoLock); + if (g_playing_file) + { + if (g_playing_file->uvox_3901) // check again now that we've acquired the lock + { + Ultravox3901 uvox_metadata; + if (uvox_metadata.Parse(g_playing_file->uvox_3901) != API_XML_FAILURE) + { + LeaveCriticalSection(&streamInfoLock); + return uvox_metadata.GetExtendedData(data, dest, (int)destlen); + } + } + else if (g_playing_file->uvox_3902) + { + Ultravox3902 uvox_metadata; + if (uvox_metadata.Parse(g_playing_file->uvox_3902) != API_XML_FAILURE) + { + LeaveCriticalSection(&streamInfoLock); + return uvox_metadata.GetExtendedData(data, dest, (int)destlen); + } + } + } + LeaveCriticalSection(&streamInfoLock); + return 0; + } + else if (_stricmp(data, "0x3901") == 0) + { + EnterCriticalSection(&streamInfoLock); + if (g_playing_file && g_playing_file->uvox_3901) // check again now that we've acquired the lock + { + if (dest == NULL) // It's empty, he's looking for the size of the 0x3901 + { + int size = MultiByteToWideChar(CP_UTF8, 0, g_playing_file->uvox_3901, -1, 0, 0); + LeaveCriticalSection(&streamInfoLock); + return size; + } + else + { + MultiByteToWideCharSZ(CP_UTF8, 0, g_playing_file->uvox_3901, -1, dest, (int)destlen); + LeaveCriticalSection(&streamInfoLock); + return 1; + } + } + LeaveCriticalSection(&streamInfoLock); + return 0; + } + else if (!_stricmp(data, "streamtype")) + { + if (lstrcmpW(lastfn, fn)) + return 0; + + if (g_playing_file) + { + EnterCriticalSection(&streamInfoLock); + if (g_playing_file) // check again now that we've acquired the lock + { + StringCchPrintfW(dest, destlen, L"%d", g_playing_file->IsStream()); + LeaveCriticalSection(&streamInfoLock); + return 1; + } + LeaveCriticalSection(&streamInfoLock); + } + + return 0; + } + else if (!_stricmp(data, "streammetadata")) + { + if (lstrcmpW(lastfn, fn)) + return 0; + + if (g_playing_file) + { + uint32_t len=0; + EnterCriticalSection(&streamInfoLock); + if (g_playing_file && g_playing_file->GetID3v2(&len) && len > 0) // check again now that we've acquired the lock + { + lstrcpynW(dest, L"1", (int)destlen); + LeaveCriticalSection(&streamInfoLock); + return 1; // always return 1 to ensure we can do title lookups + } + LeaveCriticalSection(&streamInfoLock); + } + return 0; + } + else if (!_stricmp(data, "streamtitle")) + { + EnterCriticalSection(&streamInfoLock); + if (g_playing_file) // check again now that we've acquired the lock + ConvertTryUTF8(g_playing_file->stream_current_title, dest, destlen); + else + dest[0]=0; + LeaveCriticalSection(&streamInfoLock); + return 1; + } + else if (!_stricmp(data, "streamname")) + { + EnterCriticalSection(&streamInfoLock); + if (g_playing_file) // check again now that we've acquired the lock + ConvertTryUTF8(g_playing_file->stream_name, dest, destlen); + else + dest[0]=0; + LeaveCriticalSection(&streamInfoLock); + return 1; + } + else if (!_stricmp(data, "streamurl")) + { + EnterCriticalSection(&streamInfoLock); + if (g_playing_file) // check again now that we've acquired the lock + ConvertTryUTF8(g_playing_file->stream_url, dest, destlen); + else + dest[0]=0; + LeaveCriticalSection(&streamInfoLock); + return 1; + } + else if (!_stricmp(data, "streamgenre")) + { + EnterCriticalSection(&streamInfoLock); + if (g_playing_file) // check again now that we've acquired the lock + ConvertTryUTF8(g_playing_file->stream_genre, dest, destlen); + else + dest[0]=0; + LeaveCriticalSection(&streamInfoLock); + return 1; + } + else if (!_stricmp(data, "streaminformation")) + { + EnterCriticalSection(&streamInfoLock); + if (g_playing_file) + g_playing_file->GetStreamInfo(dest, destlen); + else + dest[0]=0; + LeaveCriticalSection(&streamInfoLock); + return 1; + } + + if (!fn || !fn[0]) return 0; + + if (!_wcsnicmp(fn, L"uvox://", 7)) + return 0; + + if (g_playing_file && PathIsURL(fn) && !lstrcmpW(lastfn, fn)) + { + EnterCriticalSection(&streamInfoLock); + uint32_t len = 0; + if (g_playing_file && g_playing_file->GetID3v2(&len) && len > 0) // check again now that we've acquired the lock + { + Metadata meta(g_playing_file, fn); + int ret = meta.GetExtendedData(data, dest, (int)destlen); + LeaveCriticalSection(&streamInfoLock); + return ret; + } + LeaveCriticalSection(&streamInfoLock); + } + + if (PathIsURL(fn)) + return 0; + + if (m_ext_get_mp3info && (!m_ext_get_mp3info->IsMe(fn) || HasFileTimeChanged(fn))) + { + m_ext_get_mp3info->Release(); + m_ext_get_mp3info=0; + } + + if (!m_ext_get_mp3info) + { + m_ext_get_mp3info = new Metadata; + m_ext_get_mp3info->Open(fn); + } + + return m_ext_get_mp3info->GetExtendedData(data, dest, (int)destlen); +} + +extern "C" + __declspec(dllexport) int winampSetExtendedFileInfoW(const wchar_t *fn, const char *data, const wchar_t *val) +{ + if (!m_ext_set_mp3info || (m_ext_set_mp3info && !m_ext_set_mp3info->IsMe(fn))) + { + if(m_ext_set_mp3info) m_ext_set_mp3info->Release(); + m_ext_set_mp3info = new Metadata; + m_ext_set_mp3info->Open(fn); + } + return m_ext_set_mp3info->SetExtendedData(data, val); +} + +extern "C" + __declspec(dllexport) int winampWriteExtendedFileInfo() +{ + // flush our read cache too :) + if(m_ext_get_mp3info) m_ext_get_mp3info->Release(); + m_ext_get_mp3info = NULL; + + if (!m_ext_set_mp3info) return 0; + + Stopper stopper; + if (m_ext_set_mp3info->IsMe(lastfn)) + stopper.Stop(); + + // just in-case something changed + if (!m_ext_set_mp3info) return 0; + + int ret = m_ext_set_mp3info->Save(); + stopper.Play(); + m_ext_set_mp3info->Release(); + m_ext_set_mp3info = NULL; + + // update last modified so we're not re-queried on our own updates + UpdateFileTimeChanged(lastfn); + + return !ret; +} + +extern "C" __declspec(dllexport) + int winampClearExtendedFileInfoW(const wchar_t *fn) +{ + Metadata meta; + if (meta.Open(fn)==METADATA_SUCCESS) + { + meta.id3v2.Clear(); + Stopper stopper; + if (meta.IsMe(lastfn)) + stopper.Stop(); + meta.Save(); + stopper.Play(); + + // update last modified so we're not re-queried on our own updates + UpdateFileTimeChanged(fn); + + return 1; + } + return 0; +}
\ No newline at end of file |