Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
880
Src/Plugins/Input/in_wmvdrm/WMInformation.cpp
Normal file
880
Src/Plugins/Input/in_wmvdrm/WMInformation.cpp
Normal file
|
@ -0,0 +1,880 @@
|
|||
#include "main.h"
|
||||
#include "WMInformation.h"
|
||||
#include "resource.h"
|
||||
#include <exception>
|
||||
#include <strsafe.h>
|
||||
|
||||
class AutoByte
|
||||
{
|
||||
public:
|
||||
AutoByte(size_t bytes)
|
||||
: data(0)
|
||||
{
|
||||
data = new BYTE[bytes];
|
||||
}
|
||||
~AutoByte()
|
||||
{
|
||||
if (data)
|
||||
delete[] data;
|
||||
data = 0;
|
||||
}
|
||||
operator void *()
|
||||
{
|
||||
return (void *)data;
|
||||
}
|
||||
|
||||
BYTE *data;
|
||||
};
|
||||
|
||||
static void StoreData(WMT_ATTR_DATATYPE type, BYTE *value, DWORD length, wchar_t *valueStr, size_t len)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case WMT_TYPE_DWORD:
|
||||
StringCchPrintf(valueStr, len, L"%lu", *(DWORD *)value);
|
||||
break;
|
||||
|
||||
case WMT_TYPE_STRING:
|
||||
lstrcpyn(valueStr, (wchar_t *)value, len);
|
||||
break;
|
||||
|
||||
case -1: // hack // if (attrName == L"WM/Text")
|
||||
StringCchPrintf(valueStr, len, L"%s/%s", UserTextDescription(value, length), UserTextString(value, length));
|
||||
break;
|
||||
case WMT_TYPE_BINARY:
|
||||
BinaryString(value, length, valueStr, len);
|
||||
break;
|
||||
case WMT_TYPE_BOOL:
|
||||
if (*(BOOL *)value)
|
||||
{
|
||||
lstrcpyn(valueStr, L"True", len);
|
||||
}
|
||||
else
|
||||
{
|
||||
lstrcpyn(valueStr, L"False", len);
|
||||
}
|
||||
break;
|
||||
case WMT_TYPE_QWORD:
|
||||
StringCchPrintf(valueStr, len, L"%I64u", *(QWORD *)value);
|
||||
break;
|
||||
case WMT_TYPE_WORD:
|
||||
StringCchPrintf(valueStr, len, L"%hu", *(WORD *)value);
|
||||
break;
|
||||
case WMT_TYPE_GUID:
|
||||
GuidString(*(GUID *)value, valueStr, len);
|
||||
break;
|
||||
default:
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_UNKNOWN,valueStr,len);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
WMInformation::WMInformation(const wchar_t *fileName, bool noBlock)
|
||||
: editor(0), editor2(0), header(0), header3(0), reader(0), header2(0), openError(false)
|
||||
{
|
||||
if (fileName && fileName[0]
|
||||
&& WMCreateEditor(&editor) == S_OK)
|
||||
{
|
||||
if (SUCCEEDED(editor->QueryInterface(&editor2)))
|
||||
{
|
||||
if (SUCCEEDED(editor2->OpenEx(fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE)))
|
||||
{
|
||||
// good to go
|
||||
editor2->QueryInterface(&header);
|
||||
editor->QueryInterface(&header2);
|
||||
editor2->QueryInterface(&header3);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
editor2 = 0;
|
||||
if (SUCCEEDED(editor->Open(fileName)))
|
||||
{
|
||||
// good to go
|
||||
editor->QueryInterface(&header);
|
||||
editor->QueryInterface(&header2);
|
||||
editor->QueryInterface(&header3);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
// can't open it through the metadata editor interface, let's open a reader
|
||||
|
||||
if (editor)
|
||||
editor->Release();
|
||||
editor = 0;
|
||||
if (editor2)
|
||||
editor2->Release();
|
||||
editor2 = 0;
|
||||
if (FAILED(WMCreateReader(0, WMT_RIGHT_PLAYBACK, &reader)))
|
||||
{
|
||||
reader = 0;
|
||||
return ;
|
||||
}
|
||||
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
callback >> this;
|
||||
|
||||
if (FAILED(reader->Open(fileName, &callback, 0)))
|
||||
{
|
||||
reader->Release();
|
||||
reader = 0;
|
||||
return ;
|
||||
}
|
||||
if (noBlock)
|
||||
WaitForEvent(hEvent, INFINITE);
|
||||
else
|
||||
WaitForSingleObject(hEvent, INFINITE);
|
||||
|
||||
CloseHandle(hEvent);
|
||||
if (openError)
|
||||
{
|
||||
reader->Release();
|
||||
reader = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
reader->QueryInterface(&header);
|
||||
reader->QueryInterface(&header2);
|
||||
reader->QueryInterface(&header3);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
WMInformation::WMInformation(IWMReader *_reader)
|
||||
: reader(0), // reader is if we create an internal reader, we don't want to save the passed one (so we don't close it on someone else :)
|
||||
editor(0), editor2(0), header(0),
|
||||
header3(0), header2(0),
|
||||
openError(false), hEvent(NULL)
|
||||
{
|
||||
if (FAILED(_reader->QueryInterface(&header)))
|
||||
header = 0;
|
||||
if (FAILED(_reader->QueryInterface(&header2)))
|
||||
header2 = 0;
|
||||
if (FAILED(_reader->QueryInterface(&header3)))
|
||||
header3 = 0; // this error is OK, we can deal with it.
|
||||
}
|
||||
|
||||
/*
|
||||
WMInformation::WMInformation(IWMSyncReader *reader)
|
||||
: editor(0), editor2(0), header(0), header3(0)
|
||||
{
|
||||
reader->QueryInterface(&header);
|
||||
reader->QueryInterface(&header3);
|
||||
}*/
|
||||
|
||||
WMInformation::WMInformation(IWMMetadataEditor *_editor)
|
||||
: editor(_editor), editor2(0), header(0),
|
||||
header3(0), reader(0), header2(0),
|
||||
openError(false), hEvent(NULL)
|
||||
{
|
||||
editor->AddRef();
|
||||
editor->QueryInterface(&editor2);
|
||||
editor->QueryInterface(&header);
|
||||
editor->QueryInterface(&header2);
|
||||
editor->QueryInterface(&header3);
|
||||
}
|
||||
|
||||
|
||||
WMInformation::~WMInformation()
|
||||
{
|
||||
if (editor)
|
||||
{
|
||||
editor->Close();
|
||||
editor->Release();
|
||||
editor = 0;
|
||||
}
|
||||
if (editor2)
|
||||
editor2->Release();
|
||||
editor2 = 0;
|
||||
if (header)
|
||||
header->Release();
|
||||
header = 0;
|
||||
if (header2)
|
||||
header2->Release();
|
||||
header2 = 0;
|
||||
if (header3)
|
||||
header3->Release();
|
||||
header3 = 0;
|
||||
if (reader)
|
||||
{
|
||||
reader->Close();
|
||||
reader->Release();
|
||||
reader = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool WMInformation::GetDataType(const wchar_t *name, WMT_ATTR_DATATYPE &type)
|
||||
{
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
WORD stream = 0;
|
||||
WORD dataLen = 0;
|
||||
if (header && SUCCEEDED(header->GetAttributeByName(&stream, name, &type, 0, &dataLen)))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
void WMInformation::DeleteAttribute(const wchar_t *attrName)
|
||||
{
|
||||
|
||||
WORD indexCount = 0;
|
||||
if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, attrName, NULL, 0, &indexCount)))
|
||||
{
|
||||
WORD *indices = new WORD[indexCount];
|
||||
if (SUCCEEDED(header3->GetAttributeIndices(0, attrName, NULL, indices, &indexCount)))
|
||||
{
|
||||
for (size_t i = 0;i != indexCount;i++)
|
||||
{
|
||||
header3->DeleteAttribute(0, indices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void WMInformation::SetAttribute_BinString(const wchar_t *attrName, wchar_t *value)
|
||||
{
|
||||
if (!header || !attrName || !value)
|
||||
return ;
|
||||
|
||||
if (!*value)
|
||||
{
|
||||
DeleteAttribute(attrName);
|
||||
return ;
|
||||
}
|
||||
|
||||
AutoChar data(value);
|
||||
header->SetAttribute(0, attrName, WMT_TYPE_BINARY, (BYTE *)(char *)data, (WORD)strlen(data));
|
||||
}
|
||||
|
||||
void WMInformation::GetAttribute_BinString(const wchar_t attrName[], wchar_t *valueStr, size_t len)
|
||||
{
|
||||
if (!header)
|
||||
{
|
||||
valueStr[0]=0;
|
||||
return ;
|
||||
}
|
||||
|
||||
WMT_ATTR_DATATYPE type;
|
||||
WORD length = 0;
|
||||
HRESULT hr;
|
||||
WORD streamNum = 0;
|
||||
if (!header || FAILED(header->GetAttributeByName(&streamNum,
|
||||
attrName,
|
||||
&type,
|
||||
0,
|
||||
&length)))
|
||||
{
|
||||
valueStr[0]=0;
|
||||
return ;
|
||||
}
|
||||
AutoByte v(length);
|
||||
BYTE *value = v.data;
|
||||
|
||||
hr = header->GetAttributeByName(&streamNum,
|
||||
attrName,
|
||||
&type,
|
||||
value,
|
||||
&length);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
valueStr[0]=0;
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
int converted = MultiByteToWideChar(CP_ACP, 0, (const char *)value, length, valueStr, len-1);
|
||||
valueStr[converted]=0;
|
||||
}
|
||||
|
||||
void WMInformation::SetAttribute(const wchar_t *attrName, wchar_t *value, WMT_ATTR_DATATYPE defaultType)
|
||||
{
|
||||
if (!header || !attrName || !value)
|
||||
return ;
|
||||
|
||||
if (!*value)
|
||||
{
|
||||
DeleteAttribute(attrName);
|
||||
return ;
|
||||
}
|
||||
|
||||
WMT_ATTR_DATATYPE type;
|
||||
|
||||
if (!GetDataType(attrName, type))
|
||||
type = defaultType;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case WMT_TYPE_DWORD:
|
||||
{
|
||||
DWORD dwordValue = wcstoul(value, 0, 10);
|
||||
header->SetAttribute(0, attrName, WMT_TYPE_DWORD, (BYTE *) &dwordValue, sizeof(dwordValue));
|
||||
}
|
||||
break;
|
||||
case WMT_TYPE_STRING:
|
||||
{
|
||||
WORD size = static_cast<WORD>((lstrlen(value) + 1) * sizeof(wchar_t));
|
||||
header->SetAttribute(0, attrName, WMT_TYPE_STRING, (BYTE *)value, size);
|
||||
}
|
||||
break;
|
||||
case WMT_TYPE_BINARY:
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
break;
|
||||
case WMT_TYPE_BOOL:
|
||||
{
|
||||
BOOL boolValue;
|
||||
if (!_wcsicmp(L"true", value))
|
||||
boolValue = TRUE;
|
||||
else
|
||||
boolValue = FALSE;
|
||||
|
||||
header->SetAttribute(0, attrName, WMT_TYPE_BOOL, (BYTE *)&boolValue, sizeof(boolValue));
|
||||
}
|
||||
break;
|
||||
case WMT_TYPE_QWORD:
|
||||
{
|
||||
{
|
||||
QWORD qwordValue = _wcstoui64(value, 0, 10);
|
||||
header->SetAttribute(0, attrName, WMT_TYPE_QWORD, (BYTE *) &qwordValue, sizeof(qwordValue));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WMT_TYPE_WORD:
|
||||
{
|
||||
{
|
||||
WORD wordValue = static_cast<WORD>(wcstoul(value, 0, 10));
|
||||
header->SetAttribute(0, attrName, WMT_TYPE_WORD, (BYTE *) &wordValue, sizeof(wordValue));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WMT_TYPE_GUID:
|
||||
{
|
||||
GUID guidValue = StringGUID(value);
|
||||
header->SetAttribute(0, attrName, WMT_TYPE_GUID, (BYTE *) &guidValue, sizeof(guidValue));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool WMInformation::GetAttributeSize(const wchar_t *name, size_t &size)
|
||||
{
|
||||
WORD stream = 0;
|
||||
WORD resultSize;
|
||||
WMT_ATTR_DATATYPE type;
|
||||
|
||||
if (!header || FAILED(header->GetAttributeByName(&stream, name, &type, 0, &resultSize)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
size = resultSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
DWORD WMInformation::GetDWORDAttr(const wchar_t name[])
|
||||
{
|
||||
WORD stream = 0;
|
||||
DWORD result;
|
||||
|
||||
WORD resultSizeWord = sizeof(result);
|
||||
DWORD resultSize = sizeof(result);
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_DWORD;
|
||||
WORD count = 1;
|
||||
WORD indices[1] = {0};
|
||||
if ((!header3
|
||||
|| FAILED(header3->GetAttributeIndices(0, name, NULL, indices, &count))
|
||||
|| FAILED(header3->GetAttributeByIndexEx(0, indices[0], 0, 0, &type, NULL, (BYTE *) &result, &resultSize)))
|
||||
&&
|
||||
(!header || FAILED(header->GetAttributeByName(&stream, name, &type, (BYTE *)&result, &resultSizeWord))))
|
||||
return 0;
|
||||
else
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
long WMInformation::GetLongAttr(const wchar_t name[])
|
||||
{
|
||||
WORD stream = 0;
|
||||
long result;
|
||||
WORD resultSize = sizeof(result);
|
||||
WMT_ATTR_DATATYPE type;
|
||||
|
||||
if (!header || FAILED(header->GetAttributeByName(&stream, name, &type, (BYTE *)&result, &resultSize)))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WMInformation::GetBoolAttr(const wchar_t name[])
|
||||
{
|
||||
WORD stream = 0;
|
||||
BOOL result;
|
||||
WORD resultSize = sizeof(result);
|
||||
WMT_ATTR_DATATYPE type;
|
||||
|
||||
if (!header || FAILED(header->GetAttributeByName(&stream, name, &type, (BYTE *)&result, &resultSize)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!result;
|
||||
}
|
||||
|
||||
bool WMInformation::IsSeekable()
|
||||
{
|
||||
return GetBoolAttr(g_wszWMSeekable);
|
||||
}
|
||||
|
||||
long WMInformation::GetLengthMilliseconds()
|
||||
{
|
||||
WORD stream = 0;
|
||||
long long duration = 0;
|
||||
WORD resultSize = sizeof(duration);
|
||||
WMT_ATTR_DATATYPE type;
|
||||
|
||||
if (!header || FAILED(header->GetAttributeByName(&stream, g_wszWMDuration, &type, (BYTE *)&duration, &resultSize)))
|
||||
{
|
||||
return -1000;
|
||||
}
|
||||
|
||||
duration /= 10000LL;
|
||||
return (long)duration;
|
||||
}
|
||||
|
||||
long WMInformation::GetBitrate()
|
||||
{
|
||||
return GetDWORDAttr(g_wszWMCurrentBitrate);
|
||||
}
|
||||
|
||||
WORD WMInformation::GetNumberAttributes()
|
||||
{
|
||||
WORD numAttr = 0;
|
||||
if ((!header3 || FAILED(header3->GetAttributeCountEx(0, &numAttr)))
|
||||
&& (!header || FAILED(header->GetAttributeCount(0, &numAttr))))
|
||||
return 0;
|
||||
else
|
||||
return numAttr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void WMInformation::GetAttribute(WORD index, wchar_t *attrName, size_t attrLen, wchar_t *valueStr, size_t valueStrLen)
|
||||
{
|
||||
wchar_t _attrName[1025] = {0};
|
||||
WORD nameLen = sizeof(_attrName) / sizeof(_attrName[0]);
|
||||
WMT_ATTR_DATATYPE type;
|
||||
WORD lang;
|
||||
WORD stream = 0;
|
||||
DWORD length = 0;
|
||||
WORD lengthWord = 0;
|
||||
|
||||
if ((!header3 || FAILED(header3->GetAttributeByIndexEx(0, index, _attrName, &nameLen, &type, &lang, 0, &length)))
|
||||
&& (!header || FAILED(header->GetAttributeByIndex(index, &stream, _attrName, &nameLen, &type, 0, &lengthWord))))
|
||||
{
|
||||
attrName[0]=0;
|
||||
valueStr[0]=0;
|
||||
return ;
|
||||
}
|
||||
if (lengthWord)
|
||||
length = lengthWord;
|
||||
|
||||
AutoByte v(length);
|
||||
BYTE *value = v.data;
|
||||
|
||||
lstrcpyn(attrName, _attrName, attrLen);
|
||||
if ((!header3 || FAILED(header3->GetAttributeByIndexEx(0, index, _attrName, &nameLen, &type, &lang, value, &length)))
|
||||
&& (!header || FAILED(header->GetAttributeByIndex(index, &stream, _attrName, &nameLen, &type, value, &lengthWord))))
|
||||
{
|
||||
attrName[0]=0;
|
||||
valueStr[0]=0;
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
if (attrName == L"WM/Text")
|
||||
{
|
||||
type = (WMT_ATTR_DATATYPE)-1; // hack
|
||||
StringCchCat(attrName, attrLen, L":");
|
||||
StringCchCat(attrName, attrLen, UserTextDescription(value, length));
|
||||
}
|
||||
StoreData(type, value, length, valueStr, valueStrLen);
|
||||
}
|
||||
|
||||
void WMInformation::GetAttribute(const wchar_t attrName[], wchar_t *valueStr, size_t len)
|
||||
{
|
||||
if (!header)
|
||||
{
|
||||
valueStr[0]=0;
|
||||
return ;
|
||||
}
|
||||
|
||||
WMT_ATTR_DATATYPE type;
|
||||
WORD length = 0;
|
||||
HRESULT hr;
|
||||
WORD streamNum = 0;
|
||||
if (!header || FAILED(header->GetAttributeByName(&streamNum,
|
||||
attrName,
|
||||
&type,
|
||||
0,
|
||||
&length)))
|
||||
{
|
||||
valueStr[0]=0;
|
||||
return ;
|
||||
}
|
||||
AutoByte v(length);
|
||||
BYTE *value = v.data;
|
||||
|
||||
hr = header->GetAttributeByName(&streamNum,
|
||||
attrName,
|
||||
&type,
|
||||
value,
|
||||
&length);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
valueStr[0]=0;
|
||||
return ;
|
||||
}
|
||||
|
||||
if (attrName == L"WM/Text")
|
||||
type = (WMT_ATTR_DATATYPE)-1; // hack
|
||||
StoreData(type, value, length, valueStr, len);
|
||||
}
|
||||
|
||||
|
||||
bool WMInformation::MakeWritable(const wchar_t *fileName)
|
||||
{
|
||||
if (!editor || !editor2)
|
||||
return false;
|
||||
|
||||
if (FAILED(editor2->OpenEx(fileName, GENERIC_READ | GENERIC_WRITE, 0)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WMInformation::Flush()
|
||||
{
|
||||
if (!editor2 || FAILED(editor->Flush()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WMInformation::IsAttribute(const wchar_t attrName[])
|
||||
{
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BOOL;
|
||||
WORD length = sizeof(BOOL);
|
||||
WORD streamNum = 0;
|
||||
BOOL value;
|
||||
if (!header || FAILED(header->GetAttributeByName(&streamNum,
|
||||
attrName,
|
||||
&type,
|
||||
(BYTE *)&value,
|
||||
&length)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !!value;
|
||||
}
|
||||
}
|
||||
|
||||
bool WMInformation::IsNotAttribute(const wchar_t attrName[])
|
||||
{
|
||||
if (!header)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BOOL;
|
||||
WORD length = sizeof(BOOL);
|
||||
WORD streamNum = 0;
|
||||
BOOL value;
|
||||
if (!header || FAILED(header->GetAttributeByName(&streamNum,
|
||||
attrName,
|
||||
&type,
|
||||
(BYTE *)&value,
|
||||
&length)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return !value;
|
||||
}
|
||||
}
|
||||
|
||||
bool WMInformation::MakeReadOnly(const wchar_t *fileName)
|
||||
{
|
||||
if (!editor || !editor2)
|
||||
return false;
|
||||
|
||||
//editor->Close();
|
||||
if (FAILED(editor2->OpenEx(fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool WMInformation::NonWritable()
|
||||
{
|
||||
if (!editor2)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void WMInformation::DeleteUserText(const wchar_t *description)
|
||||
{
|
||||
WORD indexCount = 0;
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BOOL;
|
||||
WORD nameLen = 128;
|
||||
if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, L"WM/Text", NULL, 0, &indexCount)))
|
||||
{
|
||||
WORD *indices = new WORD[indexCount];
|
||||
if (SUCCEEDED(header3->GetAttributeIndices(0, L"WM/Text", NULL, indices, &indexCount)))
|
||||
{
|
||||
for (size_t index = 0;index != indexCount;index++)
|
||||
{
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
|
||||
WORD lang = 0;
|
||||
DWORD length = 0;
|
||||
wchar_t _attrName[128] = L"WM/Text";
|
||||
if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, 0, &length)))
|
||||
{
|
||||
AutoByte v(length);
|
||||
BYTE *value = v.data;
|
||||
|
||||
if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, value, &length)))
|
||||
{
|
||||
if (UserTextDescription(value, length) == description)
|
||||
{
|
||||
header3->DeleteAttribute(0, indices[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WMInformation::SetUserText(const wchar_t *description, const wchar_t *valueStr)
|
||||
{
|
||||
if (!header3 || !description || !valueStr)
|
||||
return;
|
||||
|
||||
WM_USER_TEXT userText;
|
||||
userText.pwszDescription = (LPWSTR)description;
|
||||
userText.pwszText = (LPWSTR) valueStr;
|
||||
|
||||
WORD index;
|
||||
header3->AddAttribute(0, L"WM/Text", &index, WMT_TYPE_BINARY, 0, (BYTE *) &userText, sizeof(userText));
|
||||
}
|
||||
|
||||
void WMInformation::ClearAllAttributes()
|
||||
{
|
||||
WORD numAttrs;
|
||||
header3->GetAttributeCountEx(0xFFFF, &numAttrs);
|
||||
while (numAttrs--)
|
||||
{
|
||||
header3->DeleteAttribute(0xFFFF, numAttrs);
|
||||
}
|
||||
}
|
||||
|
||||
bool WMInformation::GetCodecName(wchar_t *storage, size_t len)
|
||||
{
|
||||
if (!header2)
|
||||
return false;
|
||||
|
||||
DWORD codecs=0;
|
||||
header2->GetCodecInfoCount(&codecs);
|
||||
for (DWORD i=0;i!=codecs;i++)
|
||||
{
|
||||
WORD nameLen=0, descriptionLen=0, infoLen = 0;
|
||||
WMT_CODEC_INFO_TYPE type;
|
||||
header2->GetCodecInfo(i, &nameLen, 0, &descriptionLen, 0, &type, &infoLen, 0);
|
||||
if (type == WMT_CODECINFO_AUDIO)
|
||||
{
|
||||
wchar_t *name = new wchar_t[nameLen];
|
||||
wchar_t *description = new wchar_t[descriptionLen];
|
||||
BYTE *info = new BYTE[infoLen];
|
||||
header2->GetCodecInfo(i, &nameLen, name, &descriptionLen, description, &type, &infoLen, info);
|
||||
lstrcpynW(storage, name, len);
|
||||
delete[] name;
|
||||
delete[]description;
|
||||
delete[] info;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WMInformation::GetPicture(void **data, size_t *len, wchar_t **mimeType, int pictype)
|
||||
{
|
||||
WORD indexCount = 0;
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
|
||||
WORD nameLen = 128;
|
||||
if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, 0, &indexCount)))
|
||||
{
|
||||
WORD *indices = new WORD[indexCount];
|
||||
if (SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, indices, &indexCount)))
|
||||
{
|
||||
for (size_t index = 0;index != indexCount;index++)
|
||||
{
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
|
||||
WORD lang = 0;
|
||||
DWORD length = 0;
|
||||
wchar_t _attrName[128] = {0};
|
||||
if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, 0, &length)))
|
||||
{
|
||||
AutoByte v(length);
|
||||
BYTE *value = v.data;
|
||||
|
||||
if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, value, &length)))
|
||||
{
|
||||
WM_PICTURE *picture = (WM_PICTURE *)value;
|
||||
if (picture->bPictureType == pictype)
|
||||
{
|
||||
*len = picture->dwDataLen;
|
||||
*data = WASABI_API_MEMMGR->sysMalloc(*len);
|
||||
memcpy(*data, picture->pbData, *len);
|
||||
wchar_t *type=0;
|
||||
if (picture->pwszMIMEType)
|
||||
type = wcschr(picture->pwszMIMEType, L'/');
|
||||
|
||||
if (type && *type)
|
||||
{
|
||||
type++;
|
||||
|
||||
wchar_t *type2 = wcschr(type, L'/');
|
||||
if (type2 && *type2) type2++;
|
||||
else type2 = type;
|
||||
|
||||
size_t mimelen = wcslen(type2)+1;
|
||||
*mimeType = (wchar_t *)WASABI_API_MEMMGR->sysMalloc(mimelen*sizeof(wchar_t));
|
||||
StringCchCopyW(*mimeType, mimelen, type2);
|
||||
}
|
||||
else
|
||||
*mimeType = 0; // unknown!
|
||||
delete[] indices;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] indices;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WMInformation::SetPicture(void *data, size_t len, const wchar_t *mimeType, int type)
|
||||
{
|
||||
WM_PICTURE picture;
|
||||
picture.bPictureType = type;
|
||||
picture.dwDataLen = len;
|
||||
picture.pbData = (BYTE *)data;
|
||||
picture.pwszDescription=L"";
|
||||
wchar_t mt[32] = {0};
|
||||
if (wcsstr(mimeType, L"/") != 0)
|
||||
{
|
||||
StringCchCopyW(mt, 32, mimeType);
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchPrintfW(mt, 32, L"image/%s", mimeType);
|
||||
}
|
||||
picture.pwszMIMEType = mt;
|
||||
return SUCCEEDED(header->SetAttribute(0, g_wszWMPicture, WMT_TYPE_BINARY, (const BYTE *)&picture, sizeof(picture)));
|
||||
}
|
||||
|
||||
bool WMInformation::HasPicture(int pictype)
|
||||
{
|
||||
WORD indexCount = 0;
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
|
||||
WORD nameLen = 128;
|
||||
if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, 0, &indexCount)))
|
||||
{
|
||||
WORD *indices = new WORD[indexCount];
|
||||
if (SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, indices, &indexCount)))
|
||||
{
|
||||
for (size_t index = 0;index != indexCount;index++)
|
||||
{
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
|
||||
WORD lang = 0;
|
||||
DWORD length = 0;
|
||||
wchar_t _attrName[128] = {0};
|
||||
if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, 0, &length)))
|
||||
{
|
||||
AutoByte v(length);
|
||||
BYTE *value = v.data;
|
||||
|
||||
if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, value, &length)))
|
||||
{
|
||||
WM_PICTURE *picture = (WM_PICTURE *)value;
|
||||
if (picture->bPictureType == pictype)
|
||||
{
|
||||
delete[] indices;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] indices;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WMInformation::DeletePicture(int pictype)
|
||||
{
|
||||
WORD indexCount = 0;
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
|
||||
WORD nameLen = 128;
|
||||
if (header3 && SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, 0, &indexCount)))
|
||||
{
|
||||
WORD *indices = new WORD[indexCount];
|
||||
if (SUCCEEDED(header3->GetAttributeIndices(0, g_wszWMPicture, NULL, indices, &indexCount)))
|
||||
{
|
||||
for (size_t index = 0;index != indexCount;index++)
|
||||
{
|
||||
WMT_ATTR_DATATYPE type = WMT_TYPE_BINARY;
|
||||
WORD lang = 0;
|
||||
DWORD length = 0;
|
||||
wchar_t _attrName[128] = {0};
|
||||
if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, 0, &length)))
|
||||
{
|
||||
AutoByte v(length);
|
||||
BYTE *value = v.data;
|
||||
|
||||
if (SUCCEEDED(header3->GetAttributeByIndexEx(0, indices[index], _attrName, &nameLen, &type, &lang, value, &length)))
|
||||
{
|
||||
WM_PICTURE *picture = (WM_PICTURE *)value;
|
||||
if (picture->bPictureType == pictype)
|
||||
{
|
||||
header3->DeleteAttribute(0, indices[index]);
|
||||
delete[] indices;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] indices;
|
||||
}
|
||||
return false;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue