mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-10 11:59:58 -05:00
Initial community commit
This commit is contained in:
315
Src/Plugins/Input/in_mp3/ExtendedInfo.cpp
Normal file
315
Src/Plugins/Input/in_mp3/ExtendedInfo.cpp
Normal file
@@ -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;
|
||||
}
|
Reference in New Issue
Block a user