Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++ and iTunes COM interface?

25 views
Skip to first unread message

Mike Frisch

unread,
Jul 28, 2004, 1:36:51 PM7/28/04
to
Is anybody doing any work with this? I am trying to write a simple app
that responds to iTunes events, but I am lost...

Here's what I did:

- created an instance of IID_IiTunes
- queried for IID_IConnectionPointContainer (CPC)
- query CPC for DIID__IiTunesEvents connection point (CP)
- called CP->Advise() with pointer to my class which inherits
_IiTunesEvents

It doesn't work :( All HRESULTs are successful, however I never receive
any event notification.

I am confused that _IiTunesEvents is defined by Apple as being an
IDispatch. What does this mean to the client side? How do I "register"
as an event sink through IDispatch? Is using the IConnectionPoint
interface incorrect?

Can somebody provide sample code or offer some hints?

Much appreciated,

Mike.

realexander

unread,
Dec 21, 2004, 2:08:52 PM12/21/04
to
I don't know if Mike still cares, but I've figured this out, and I
hereby submit it to the collective knowledge base.

Using MFC, I created a class derived from CCmdTarget. _IiTunesEvents is
derived from IDispatch, so I created a dispatch map that matches the
expected events.

The iTunesEventHandler.h file is:

---------
#if
!defined(AFX_ITUNESEVENTHANDLER_H__42970B2C_41F2_4339_8DCC_9AC7D5550402__INCLUDED_)
#define
AFX_ITUNESEVENTHANDLER_H__42970B2C_41F2_4339_8DCC_9AC7D5550402__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// iTunesEventHandler.h : header file
//

#include "iTunesCOMInterface.h" // from Apple's iTunes SDK

/////////////////////////////////////////////////////////////////////////////
// CiTunesEventHandler command target

class CiTunesEventHandler : public CCmdTarget
{
public:
CiTunesEventHandler();
virtual ~CiTunesEventHandler();

// Attributes
public:

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CiTunesEventHandler)
public:
virtual void OnFinalRelease();
//}}AFX_VIRTUAL

// Implementation
protected:

// Generated message map functions
//{{AFX_MSG(CiTunesEventHandler)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG

DECLARE_MESSAGE_MAP()
// Generated OLE dispatch map functions
//{{AFX_DISPATCH(CiTunesEventHandler)
afx_msg void OnDatabaseChangedEvent(const VARIANT FAR&
deletedObjectIDs, const VARIANT FAR& changedObjectIDs);
afx_msg void OnPlayerPlayEvent(const VARIANT FAR& iTrack);
afx_msg void OnPlayerStopEvent(const VARIANT FAR& iTrack);
afx_msg void OnPlayerPlayingTrackChangedEv(const VARIANT FAR& iTrack);
afx_msg void OnUserInterfaceEnabledEvent();
afx_msg void OnCOMCallsDisabledEvent(short reason);
afx_msg void OnCOMCallsEnabled();
afx_msg void OnQuittingEvent();
afx_msg void OnAboutToPromptUserToQuitEvent();
afx_msg void OnSoundVolumeChangedEvent(long newVolume);
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()

LPUNKNOWN GetInterfaceHook(const void *piid);
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately
before the previous line.

#endif //
!defined(AFX_ITUNESEVENTHANDLER_H__42970B2C_41F2_4339_8DCC_9AC7D5550402__INCLUDED_)
---------

The iTunesEventHandler.cpp file is:

---------
// iTunesEventHandler.cpp : implementation file
//

#include "stdafx.h"
#include "iTunesEventHandler.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CiTunesEventHandler

CiTunesEventHandler::CiTunesEventHandler()
{
EnableAutomation();
}

CiTunesEventHandler::~CiTunesEventHandler()
{
}


void CiTunesEventHandler::OnFinalRelease()
{
// When the last reference for an automation object is released
// OnFinalRelease is called. The base class will automatically
// deletes the object. Add additional cleanup required for your
// object before calling the base class.

CCmdTarget::OnFinalRelease();
}


BEGIN_MESSAGE_MAP(CiTunesEventHandler, CCmdTarget)
//{{AFX_MSG_MAP(CiTunesEventHandler)
// NOTE - the ClassWizard will add and remove mapping macros here.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BEGIN_DISPATCH_MAP(CiTunesEventHandler, CCmdTarget)
//{{AFX_DISPATCH_MAP(CiTunesEventHandler)
DISP_FUNCTION(CiTunesEventHandler, "OnDatabaseChangedEvent",
OnDatabaseChangedEvent, VT_EMPTY, VTS_VARIANT VTS_VARIANT)
DISP_FUNCTION(CiTunesEventHandler, "OnPlayerPlayEvent",
OnPlayerPlayEvent, VT_EMPTY, VTS_VARIANT)
DISP_FUNCTION(CiTunesEventHandler, "OnPlayerStopEvent",
OnPlayerStopEvent, VT_EMPTY, VTS_VARIANT)
DISP_FUNCTION(CiTunesEventHandler, "OnPlayerPlayingTrackChangedEv",
OnPlayerPlayingTrackChangedEv, VT_EMPTY, VTS_VARIANT)
DISP_FUNCTION(CiTunesEventHandler, "OnUserInterfaceEnabledEvent",
OnUserInterfaceEnabledEvent, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(CiTunesEventHandler, "OnCOMCallsDisabledEvent",
OnCOMCallsDisabledEvent, VT_EMPTY, VTS_I2)
DISP_FUNCTION(CiTunesEventHandler, "OnCOMCallsEnabled",
OnCOMCallsEnabled, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(CiTunesEventHandler, "OnQuittingEvent", OnQuittingEvent,
VT_EMPTY, VTS_NONE)
DISP_FUNCTION(CiTunesEventHandler, "OnAboutToPromptUserToQuitEvent",
OnAboutToPromptUserToQuitEvent, VT_EMPTY, VTS_NONE)
DISP_FUNCTION(CiTunesEventHandler, "OnSoundVolumeChangedEvent",
OnSoundVolumeChangedEvent, VT_EMPTY, VTS_I4)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()

// Note: we add support for IID_IiTunesEventHandler to support typesafe
binding
// from VBA. This IID must match the GUID that is attached to the
// dispinterface in the .ODL file.

// {429DD3C8-703E-4188-960E-A9821F14B04C}
static const IID IID_IiTunesEventHandler =
{ 0x429dd3c8, 0x703e, 0x4188, { 0x96, 0xe, 0xa9, 0x82, 0x1f, 0x14,
0xb0, 0x4c } };

BEGIN_INTERFACE_MAP(CiTunesEventHandler, CCmdTarget)
INTERFACE_PART(CiTunesEventHandler, IID_IiTunesEventHandler, Dispatch)
END_INTERFACE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CiTunesEventHandler message handlers

//////////////////////////////////////////////////////////////////////
LPUNKNOWN CiTunesEventHandler::GetInterfaceHook(const void *piid)
{
REFIID iid = *(IID *) piid;
if (iid == DIID__IiTunesEvents)
return GetIDispatch(FALSE);
else
return NULL;
}

//////////////////////////////////////////////////////////////////////
void CiTunesEventHandler::OnDatabaseChangedEvent(const VARIANT &
/*deletedObjectIDs*/, const VARIANT & /*changedObjectIDs*/)
{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnPlayerPlayEvent(const VARIANT & /*iTrack*/)

{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnPlayerStopEvent(const VARIANT & /*iTrack*/)

{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnPlayerPlayingTrackChangedEv(const VARIANT &
/*iTrack*/)
{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnUserInterfaceEnabledEvent()
{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnCOMCallsDisabledEvent(short /*reason*/)
{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnCOMCallsEnabled()
{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnQuittingEvent()
{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnAboutToPromptUserToQuitEvent()
{
// TODO: Add your dispatch handler code here

}

void CiTunesEventHandler::OnSoundVolumeChangedEvent(long /*newVolume*/)

{
// TODO: Add your dispatch handler code here

}

-------

In another class, I instantiate a CiTunesEventHandler object and create
a connection point to it from iTunes:

-------

//////////////////////////////////////////////////////////////////////
CComPtr<IiTunes> CiTunesInterface::ITunes()
{
if (m_iTunes == NULL)
{
m_iTunes.CoCreateInstance(CLSID_iTunesApp, NULL,
CLSCTX_LOCAL_SERVER);
CComQIPtr<IConnectionPointContainer> cpCont(m_iTunes);
if (cpCont)
{
if (SUCCEEDED(cpCont->FindConnectionPoint(DIID__IiTunesEvents,
&m_connectionPoint)))
{
CComQIPtr<_IiTunesEvents> ev(m_eventHandler.GetIDispatch(FALSE));
m_connectionPoint->Advise(m_eventHandler.GetIDispatch(FALSE),
&m_cookie);
}
}
}
return m_iTunes;
}

-------

The relevant variables used in the above code are:

-------

CComPtr<IiTunes> m_iTunes;
CComPtr<IConnectionPoint> m_connectionPoint;
DWORD m_cookie;
CiTunesEventHandler m_eventHandler;

-------

Remember to unadvise the connection point when you're shutting down.
Hope this helps someone.

- Bob Alexander

0 new messages