Я создал приложение Qt (5.7), которое взаимодействует с API-интерфейсом проигрывателя Windows Media для анализа метаданных. По какой-то явной причине мое приложение падает при обращении к IWMPMedia3::getAttributeCountByType
,
Строка, в которой происходит сбой:
if (pMedia3Item && pMedia3Item->getAttributeCountByType(L"TrackingID", 0, &l) == S_OK) //Will eventually crash here
Он не падает в первом случае, он занимает пару сотен циклов и, кажется, связан с тем, когда вызов повторно возвращается 0
, Если я переключаюсь на атрибут, который, как я знаю, существует, он работает нормально.
То, что размещено ниже, это объект, удаленный назад, но он все еще падает. Этот объект предназначен для запуска в своем собственном QThread
и все символы COM определены и содержатся в QThread
,
Код является частью более крупного приложения, которое использует многие другие модули Qt, GUI, веб-движок — два самых больших.
#include "WMPMLImport.h"#include <QDebug>
#include "Wininet.h"
#define WMP_CLSID L"{6BF52A52-394A-11d3-B153-00C04F79FAA6}"#define WMP_REFIID L"{D84CCA99-CCE2-11d2-9ECC-0000F8085981}"
#define WMP_PL_ALL_MUSIC L"All Music"
#define SAFE_RELEASE(ptr) if(NULL!=(ptr)){(ptr)->Release();ptr=NULL;}
#define BSTR_RELEASE(bstr) {SysFreeString(bstr);(bstr)=NULL;}
class CCoInitialize
{
public:
CCoInitialize() :
m_hr(CoInitialize(NULL))
{}
~CCoInitialize()
{
if(SUCCEEDED(m_hr)) {
qDebug() << "CCoInitialize: DTOR";
CoUninitialize();
}
}
HRESULT m_hr;
};
/**
Worker class that will step through the WMP COM interface
and extact the audio meta data contained within it,
*/
class WMPMLComHandler : public QObject
{
public:
WMPMLComHandler(WMPMLImport* t) :
m_thread(t)
{
qDebug() << "WMPMLComHandler::CTOR" << QThread::currentThreadId();
}
~WMPMLComHandler()
{
qDebug() << "WMPMLComHandler::DTOR" << QThread::currentThreadId();
}
/**
Method responsible for walking through the COM interface and extracting
all the track and playlist metadata including the artwork.
@returns Return false if the COM API was not parsed correctly.
*/
bool parse()
{
bool b = true;
CCoInitialize cCoInit;
IWMPCore* pIWMPCore = NULL;
IWMPCore3* pIWMPCore3 = NULL;
IWMPPlaylistCollection *pPlaylistCollection;
IWMPPlaylist *pMainLibplaylist;
CLSID clsID;
CLSID refID;
CLSIDFromString(WMP_CLSID, &clsID);
CLSIDFromString(WMP_REFIID, &refID);
if(SUCCEEDED(CoCreateInstance(clsID, NULL, CLSCTX_ALL, refID, (void**)&pIWMPCore)))
{
if(SUCCEEDED(pIWMPCore->get_playlistCollection(&pPlaylistCollection)))
{
if(SUCCEEDED(pIWMPCore->QueryInterface(__uuidof(IWMPCore3), reinterpret_cast<void**>(&pIWMPCore3))))
{
IWMPPlaylistArray* pPlaylistArray = NULL;
if(SUCCEEDED(pPlaylistCollection->getAll(&pPlaylistArray)))
{
long playlistCount = 0;
if(SUCCEEDED(pPlaylistArray->get_count(&playlistCount)))
{
IWMPPlaylist* pPlaylist = NULL;
for(int playlistIndex=0; playlistIndex < playlistCount; playlistIndex++)
{
if (SUCCEEDED(pPlaylistArray->item(playlistIndex, &pPlaylist)))
{
long lMediaCount = 0;
if (SUCCEEDED(pPlaylist->get_count(&lMediaCount)))
{
fetchPlaylist(pPlaylist, NULL, playlistIndex, lMediaCount);
}
SAFE_RELEASE(pPlaylist);
}
}
}
SAFE_RELEASE(pPlaylistArray);
}
SAFE_RELEASE(pIWMPCore3);
}
SAFE_RELEASE(pPlaylistCollection);
}
SAFE_RELEASE(pIWMPCore);
}
SAFE_RELEASE(pMainLibplaylist);
return b;
}
private:
void fetchPlaylist(IWMPPlaylist* pPlaylist, BSTR bstrName, unsigned int playlistIndex, long count)
{
//get the playlist items
for(long mediaIndex=0; mediaIndex<count-1; mediaIndex++)
{
IWMPMedia* pMediaItem = NULL;
if(SUCCEEDED(pPlaylist->get_item(mediaIndex, &pMediaItem)))
{
IWMPMedia3 *pMedia3Item = NULL;
if (pMediaItem->QueryInterface(__uuidof(IWMPMedia3), reinterpret_cast<void **>(&pMedia3Item)) == S_OK)
{
long l = 0;
qDebug() << "About to call method for" << mediaIndex << "time";
if (pMedia3Item && pMedia3Item->getAttributeCountByType(L"TrackingID", 0, &l) == S_OK) //Will eventually crash here
{
qDebug() << "Exited method for" << mediaIndex << "time";
}
}
SAFE_RELEASE(pMedia3Item);
SAFE_RELEASE(pMediaItem);
}
}
qDebug() << "*********COMPLETE*********";
}
WMPMLImport* m_thread;
};
//==
WMPMLImport::WMPMLImport() :
m_comHandler(NULL)
{
qDebug() << "WMPMLImporter CTOR" << QThread::currentThreadId();
}
WMPMLImport::~WMPMLImport()
{
}
/**
Reimplemented function that runs the function contents in a new thread context.
The parsing of the COM is all ran through this thread. Returning out of this
thread will end its execution.
*/
void WMPMLImport::run()
{
QMutexLocker g(&m_lock);
m_comHandler = new WMPMLComHandler(this);
g.unlock();
bool parseOk = m_comHandler->parse();
g.relock();
delete m_comHandler;
m_comHandler = NULL;
}
Задача ещё не решена.
Других решений пока нет …