Question

I am just try to write simple program for some practice. But iTunes COM for Windows SDK threw me a little surprise. I am want to create playlist and add file to it but when i call IITUserPlaylist::AddFile program crash with access violation. I can all other methods like Delete etc.

Project (MSVC10): http://www76.zippyshare.com/v/34795637/file.html

#include <iostream>
#include <windows.h>
#include <comutil.h>
#include "iTunesCOMInterface.h"

int main(int argc, char* argv[])
{
CoInitialize(0);

HRESULT  hRes;
IiTunes* itunes = 0;

// note - CLSID_iTunesApp and IID_IiTunes are defined in iTunesCOMInterface_i.c
hRes = ::CoCreateInstance(CLSID_iTunesApp, NULL, CLSCTX_LOCAL_SERVER, IID_IiTunes, (PVOID *)&itunes);
if(hRes != S_OK && itunes == nullptr)
{
    std::cout << "Can not create iTunesApp instance" << std::endl;
    CoUninitialize();
    return 1;
}

IITLibraryPlaylist* mainLibrary = 0;
hRes = itunes->get_LibraryPlaylist(&mainLibrary);
if(hRes != S_OK || mainLibrary == 0)
{
    std::cout << "Can not get main library" << std::endl;

    itunes->Release();
    CoUninitialize();
    return 1;
}


IITSource* mainLibrarySource = 0;
hRes = itunes->get_LibrarySource(&mainLibrarySource);
if(hRes != S_OK || mainLibrarySource == 0)
{
    std::cout << "Can not get library source" << std::endl;

    mainLibrary->Release();
    itunes->Release();
    CoUninitialize();
    return 1;
}

IITPlaylistCollection* playlistCollection = 0;
hRes = mainLibrarySource->get_Playlists(&playlistCollection);
if(hRes != S_OK || playlistCollection == 0)
{
    std::cout << "Can not get source playlists" << std::endl;

    mainLibrarySource->Release();
    mainLibrary->Release();
    itunes->Release();
    CoUninitialize();
    return 1;
}

BSTR playlistName = SysAllocString(L"SoundFrost playlist");

IITPlaylist* ownPlaylist = 0;
//TODO: But there can be additional playlists with the same name, since playlist names are not unique
hRes = playlistCollection->get_ItemByName(playlistName, &ownPlaylist);
if(hRes != S_OK || ownPlaylist == 0)
{
    //just create new
    hRes = itunes->CreatePlaylist(playlistName, &ownPlaylist);
    if(hRes != S_OK || ownPlaylist == 0)
    {
        std::cout << "Can not create playlist";

        SysFreeString(playlistName);

        playlistCollection->Release();
        mainLibrarySource->Release();
        mainLibrary->Release();
        itunes->Release();
        CoUninitialize();
        return 1;
    }
}
SysFreeString(playlistName);

ITPlaylistKind playlistKind;
hRes = ownPlaylist->get_Kind(&playlistKind);
if(hRes == S_OK && playlistKind == ITPlaylistKindUser)
{
    IITUserPlaylist* ownUserPlaylist = static_cast<IITUserPlaylist*>(ownPlaylist);
    if(ownUserPlaylist != 0)
    {
        BSTR filePath = SysAllocString(L"C:\\test.mp3");
        IITOperationStatus* status;
        //hRes = mainLibrary->AddFile(filePath, &status);
        //hRes = ownUserPlaylist->AddFile(filePath, &status);
        SysFreeString(filePath);
    }
}

playlistCollection->Release();
ownPlaylist->Release();
mainLibrarySource->Release();
mainLibrary->Release();
itunes->Release();

CoUninitialize();

return 0;

}

If i call IITLibraryPlaylist::AddFile all was right. Just uncomment 95 or 96 line for test.

Simple C# code works fine:

iTunesApp itunes = new iTunesLib.iTunesApp();
IITUserPlaylist playlist = itunes.CreatePlaylist("C# playlist") as IITUserPlaylist;
IITOperationStatus status = playlist.AddFile("C:\\test.mp3");

I can not understand why this is happening.

Was it helpful?

Solution

You can't really do this with COM:

IITUserPlaylist* ownUserPlaylist = static_cast<IITUserPlaylist*>(ownPlaylist);

You're just casting an interface pointer into another interface pointer. You must do a QueryInterface instead:

HRESULT hr = ownPlaylist->QueryInterface(IID_IITUserPlaylist, (void**)&ownUserPlaylist);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top