Click here to Skip to main content
11,641,081 members (59,241 online)
Click here to Skip to main content

Extracting iTunes Data and Responding to its Events using iTunes SDK and C++

, 28 Aug 2006 CPOL 36.3K 563 25
Rate this:
Please Sign up or sign in to vote.
An article to show how iTunes SDK can be used to get all the songs and playlists of iTunes, getting Art work and getting the event notification from iTunes
Sample Image - iTunes_interact.jpg


Around a year ago, I was writing a plug-in for one Media related application which extracts all the media items, meta-data and play lists from iTunes. The plug-in also responds to the events of iTunes like its database change due to addition/deletion of media item to/from iTunes. In this article, a very simple application is presented which loads all the data from iTunes by using the iTunes SDK and responds to its database change event by reloading all the data again. At that time not much resources were available on the internet dealing with the iTunes SDK, but I was not able to publish this article due to some non-technical issues. Some days back, I found that there are still not many resources available on CodeProject which deal with this iTunes SDK in C++. Most of the articles relating to iTunes SDK deal with C#, so I decided to write one article on this topic though it is very late.

The sample given here was originally written with iTunes version 5. I've tested it with the latest iTunes (ver and it is working fine.

How to Use the Demo

You need to install iTunes, if it is not installed and add some media item to it. You'll get all the media items of iTunes in the sample and Artwork will be shown if the item is clicked, if any artwork is available. If you add/remove some item from the iTunes, the sample will also get updated.

Using the Code

All the media items added to iTunes come under Library tab. The loading of iTunes media item can be done in two ways. We can either load all the media items through Library or we can load it by play lists. In the sample, all data have been loaded through library. Here is the code snippet:

    HRESULT hr;
    CComPtr<IITUNES> spITunesApp;
    // note - CLSID_iTunesApp and IID_IiTunes are defined in iTunesCOMInterface_i.c
    //create iTunes component
     hr = ::CoCreateInstance(CLSID_iTunesApp, 
                                    NULL, CLSCTX_LOCAL_SERVER,//local server 
                                    (void **)&spITunesApp);    

        AfxMessageBox("Failed to load iTunes Component, is iTunes installed????");

#if 1          //connection point to receive database change notification
    IConnectionPointContainer  * pCPC;

    hr=spITunesApp->QueryInterface(IID_IConnectionPointContainer,(void **)&pCPC);

    IConnectionPoint * pCP;

    _IiTunesEvents * pITEvent;
    hr=pCPC->FindConnectionPoint (__uuidof(pITEvent),&pCP);

    IUnknown *pSinkUnk;
    CITunesEventSink * pSink;
    pSink=new CITunesEventSink;
    hr = pSink->QueryInterface (IID_IUnknown,(void **)&pSinkUnk);

    DWORD dwAdvise;
    hr = pCP->Advise(pSinkUnk,&dwAdvise); 


    CComPtr <IITSOURCECOLLECTION>  spSourceCollection;

    //check whether iTunes is already executing
    //if it is not executing then we'll hide it
    BOOL bRes=IsITunesNeedsToBeHidden();
    HANDLE hThread;

    //itunes pops up when we call 
    //the function of its component
    //so hide it by this patchy method...
    if(bRes) //iTunes was not there so we need to hide it
        //create auto reset events

        //strat the thread to hide iTunes
        //wait till the thread starts
        //get source collection
        //stop iTunes hide thread
        //wait till the thread stops
        //Now minimize iTunes and Hide
    else //iTunes was there so need to hide do normal things
        //get source collection
        if(FAILED(hr) || hr==S_FALSE)
   long countSource;
   long countPlaylist;
   long countTracklist;
   //get the source count 
   hr=spSourceCollection->get_Count (&countSource);
   CComPtr<IITSOURCE>  spSource;
   CComPtr<IITPLAYLISTCOLLECTION> spPlaylistCollection;
   CComPtr<IITPLAYLIST> spPlaylist;
   CComPtr<IITTRACKCOLLECTION>  spTrackCollection; 
   CComPtr<IITARTWORK>  spAlbumArt;
   CComPtr<IITARTWORKCOLLECTION> spAlbumArtCollection;
   ITArtworkFormat artFormat;
   CComBSTR bstrName;
   CComBSTR bstrLocation;
   CComBSTR bstrArtist;
   CComBSTR bstrAlbum;
   CComBSTR bstrTime;
   CComBSTR bstrYear;
   CComBSTR bstrAlbumArtPath;
   char szAlbumArtPath[255];
   hr=spSourceCollection->get_Item (1,&spSource);
       spSource->get_Playlists (&spPlaylistCollection);
       spPlaylistCollection->get_Count (&countPlaylist);
       hr=spPlaylistCollection->get_Item (1,&spPlaylist);
       spPlaylist->get_Tracks (&spTrackCollection);
       spTrackCollection->get_Count (&countTracklist);

       m_ListCtrl.DeleteAllItems ();

       for(long k=1;k<=countTracklist;k++)
           CComPtr<IITTRACK>  spTrack;          
           hr=spTrackCollection->get_Item (k,&spTrack);
           spTrack->get_Name (&bstrName);

           CComPtr<IITFILEORCDTRACK> spFileTrack;

           hr=spTrack->QueryInterface (__uuidof(spFileTrack),(void **)&spFileTrack);
           //Get the ArtWork
           hr=spTrack->get_Artwork (&spAlbumArtCollection);
           hr=spAlbumArtCollection->get_Item (1,&spAlbumArt);

           if(SUCCEEDED(hr) && hr!=S_FALSE)
               hr=spAlbumArt->get_Format (&artFormat);
                   CString strTemp=OLE2T(bstrName);
                   strTemp.TrimLeft ("\"");
                   strTemp.TrimRight ("\"");

		  "%s%s%s%d%s",m_szCurDir,"\\",strTemp.GetBuffer (),k,".");
                   case ITArtworkFormatJPEG:
                       hr=spAlbumArt->SaveArtworkToFile (bstrAlbumArtPath);
                   case ITArtworkFormatPNG :
                       spAlbumArt->SaveArtworkToFile (bstrAlbumArtPath);
                   case ITArtworkFormatBMP:
                       spAlbumArt->SaveArtworkToFile (bstrAlbumArtPath);

           spFileTrack->get_Location (&bstrLocation);
           spTrack->get_Artist (&bstrArtist);
           spTrack->get_Album (&bstrAlbum);
           spTrack->get_Time (&bstrTime);
           // pTrack->get_Year (&bstrYear);
           LV_ITEM item;
           item.mask = LVIF_TEXT | LVIF_IMAGE;
           item.iItem = m_ListCtrl.GetItemCount();
           item.iImage = (k-1) % 5;
           item.iSubItem = 0;
           item.cchTextMax = 255;
           item.pszText = OLE2T(bstrName);
           m_ListCtrl.InsertItem (&item);

           item.pszText = OLE2T(bstrLocation);
           item.iSubItem = 1;

           item.pszText = OLE2T(bstrArtist);
           item.iSubItem = 2;

           item.pszText = OLE2T(bstrAlbum);
           item.iSubItem = 3;

           item.pszText = OLE2T(bstrTime);
           item.iSubItem = 4;

//   AfxMessageBox("Now going to show Unsmart Playlist items....");
//   UnsmartListItems(pITunes);


The play list wise media item loading is also shown in the function UnsmartListItems(IiTunes *pITunes).

void UnsmartListItems(IiTunes *pITunes)
    long lSourceID;
    long lPlaylistID;
    long lTrackId;
    long countSource;
    IITObject * pObject;
//    IITUserPlaylist * pUserPlaylist;
    IITSourceCollection * pCollection;      

    short bIsSmart=0;

    HRESULT hr=pITunes->get_Sources(&pCollection); 
    hr=pCollection->get_Count (&countSource);

    IITSource * pSource;
    IITPlaylistCollection * pPlaylistCollection;
    IITPlaylist * pPlaylist;
    IITTrackCollection * pTrackCollection;
    IITTrack * pTrack;

    CComPtr<IITFILEORCDTRACK> fileTrack;

    long countPlaylist;
    long countTracklist;
    CComBSTR bstrName;

    for(long i=1;i<=countSource;i++)
        hr=pCollection->get_Item (i,&pSource);
        pSource->get_SourceID (&lSourceID);
        pSource->get_Playlists (&pPlaylistCollection);
        pPlaylistCollection->get_Count (&countPlaylist);
        for(long j=1;j<=countPlaylist;j++)
            hr=pPlaylistCollection->get_Item (j,&pPlaylist);
            pPlaylist->get_PlaylistID (&lPlaylistID);            
            hr=pITunes->GetITObjectByID (lSourceID,lPlaylistID,0,0,&pObject);
            pObject->get_Name (&bstrName);

            CComPtr<IITUSERPLAYLIST> spUserPlaylist; 

                    ITUserPlaylistSpecialKind  plKind;
                    spUserPlaylist->get_SpecialKind (&plKind);
                        pPlaylist->get_Tracks (&pTrackCollection);
                        pTrackCollection->get_Count (&countTracklist);

                        //m_ListCtrl.DeleteAllItems ();
                        for(long k=1;k<=countTracklist;k++)
                            hr=pTrackCollection->get_Item (k,&pTrack);
                            pTrack->get_Name (&bstrName);

Points of Interest

In the sample, all the media items load code has been called from the main thread of the application. It should be put in a separate worker thread. It has just been put here for simplicity.

One pesky thing about the Tunes SDK is that whenever you call any of the iTunes component's methods, the iTunes UI will pop up. I couldn't find any way to block it, so in this sample iTunes has been hidden in a patchy way which results in a flicker in slow PCs.


I hope you guys find this sample helpful when you are going to interact with iTunes SDK. You can contact me, if you have anything to ask.


This sample uses code from two articles on CodeProject:

  1. Alternate row coloring CListCtrl by sdancer75, George Papaioannou
  2. WallpaperQ by Jason Henderson, for previewing album art in thumbnails


  • 28th August, 2006: Initial post 


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior)
India India
Anindya Sengupta is a Software Developer from the eastern part of India, working on C/C++/VC++/MFC/COM/ATL/DirectX. When he is not writing code he may be listening to some songs of R.E.M or Green Day.

You may also be interested in...

Comments and Discussions

QuestionGetting Event Parameters Pin
dshiells27-Nov-13 1:47
memberdshiells27-Nov-13 1:47 
GeneralUsing the article example for a simple non MFC script Pin
pardillojuegos29-Jun-12 6:27
memberpardillojuegos29-Jun-12 6:27 
GeneralExtracting data from iPhone using iTunes Pin
srajput1-Apr-10 1:26
membersrajput1-Apr-10 1:26 
GeneralCoverart Doesn't Work Pin
MicealG31-Aug-07 0:33
memberMicealG31-Aug-07 0:33 
GeneralFolders... Pin
samyeling25-Oct-06 2:28
membersamyeling25-Oct-06 2:28 
GeneralRe: Folders... Pin
anindya_sengupta26-Oct-06 0:38
memberanindya_sengupta26-Oct-06 0:38 
GeneralRe: Folders... Pin
cziy12225-Nov-09 4:21
membercziy12225-Nov-09 4:21 
GeneraliTunes Listview Pin
viperbone29-Sep-06 1:42
memberviperbone29-Sep-06 1:42 
GeneralRe: iTunes Listview Pin
anindya_sengupta2-Oct-06 20:48
memberanindya_sengupta2-Oct-06 20:48 
GeneralRe: iTunes Listview Pin
viperbone11-Nov-07 5:51
memberviperbone11-Nov-07 5:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150731.1 | Last Updated 28 Aug 2006
Article Copyright 2006 by anindya_sengupta
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid