Using the COM interface with VS2017 and plain C++

This forum is for questions / discussions regarding development of addons / tweaks for MediaMonkey for Windows 4.

Moderators: Gurus, Addon Administrators

dplummer
Posts: 9
Joined: Sat Dec 20, 2008 12:55 pm

Using the COM interface with VS2017 and plain C++

Post by dplummer »

All,

I know that the COM interface is deprecated and also appreciate that C++ is rather long in the tooth but I am where I am, trying to port some existing Python code that works with win32com into an existing c++ console application developed under Visual Studio 2017.

So far I have generated an IDL file from MediaMonkey.exe (4.1.20) and (after addition of some forward definitions) got it to compile .h and .c files which I have added to my project.

My problem now is that I cannot work out how to instantiate an SDB object to start working with.

I was expecting something like: SongsDB::SDBApplication SDB = new SongsDB::SDBApplication();
But SongsDB is not recognised

I have also tried using #import on the MM executable but my .tld file is failing to compile because various terms (such as EOF) have been #defined elsewhere and generate errors.

If someone could give me some pointers please I would be very grateful.

Many thanks
Dave
Best Regards
Dave Plummer
Norwich UK
MMW user since 2008, MMA user since release
PetrCBR
Posts: 1763
Joined: Tue Mar 07, 2006 5:31 pm
Location: Czech
Contact:

Re: Using the COM interface with VS2017 and plain C++

Post by PetrCBR »

Probably something like this could work ?

Code: Select all

ISDB *pSDB;
hr = CoCreateInstance(CLSID_SDB, NULL, CLSCTX_INPROC_SERVER, IID_SDB, reinterpret_cast<void**>(&pSDB));
How to make a debuglog - step 4b: viewtopic.php?f=30&t=86643
dplummer
Posts: 9
Joined: Sat Dec 20, 2008 12:55 pm

Re: Using the COM interface with VS2017 and plain C++

Post by dplummer »

Many thanks petrCBR,

With a bit of tweaking that did the trick. Here is a working fragment:

Code: Select all

	CoInitialize(NULL);
	ISDBApplication *pSDB;
	HRESULT hr = CoCreateInstance(CLSID_SDBApplication, NULL, CLSCTX_LOCAL_SERVER, IID_ISDBApplication, reinterpret_cast<void**>(&pSDB));
	if (hr!=S_OK) {
		printf("Failed to create instance: %x\n", hr);
		return;
	}

	// Keep opened instance running after disconnect
	pSDB->put_ShutdownAfterDisconnect(false);    

	// Start the current track playing
	ISDBPlayer* pPlayer;
	pSDB->get_Player(&pPlayer);
	pPlayer->Play();
Best regards

Dave
Best Regards
Dave Plummer
Norwich UK
MMW user since 2008, MMA user since release
dplummer
Posts: 9
Joined: Sat Dec 20, 2008 12:55 pm

Re: Using the COM interface with VS2017 and plain C++

Post by dplummer »

Hi again,

I had really hoped that I could work this out for myself but I have failed to get a result from QuerySongs with the c++ interface.

I have successfully accessed the interface and can control the player. However I have been reading as much background as I can and beating my head against a brick wall but am getting nowhere.

QuerySongs runs and returns an IDispatch object pointer. The documentation says that the it should return a SongIterator object but I cannot discover how to either extract SongIterator from the IDispatch or to get it from the ISDBDatabase object. This works from Python with WIN32COM so I think I must have a fundamental misunderstanding of something.

If anyone is able to point me in a helpful direction I would really appreciate it.

Thanks in advance
Best Regards
Dave Plummer
Norwich UK
MMW user since 2008, MMA user since release
Peke
Posts: 17446
Joined: Tue Jun 10, 2003 7:21 pm
Location: Earth
Contact:

Re: Using the COM interface with VS2017 and plain C++

Post by Peke »

Maybe something like

Code: Select all

ISDBDatabase* pDatabase;
	pSDB->get_Database(&pDatabase);
	ISDBSongIterator* pSDBIterator
	get_Iterator(&pDatabase->QuerySongs());
Forgive me if I'm wrong this is not my stronger side.

Also do not extract check EOF result and if NOT Get ITEM and Call NEXT like with pPlayer->Play() til you get what you want or EOF.
Best regards,
Peke
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
Image
Image
Image
How to attach PICTURE/SCREENSHOTS to forum posts
dplummer
Posts: 9
Joined: Sat Dec 20, 2008 12:55 pm

Re: Using the COM interface with VS2017 and plain C++

Post by dplummer »

Thanks for the reply Pavle,

This is not quite right and I am still struggling.

My code is:

Code: Select all

		ISDBDatabase *pSDBDatabase;
		pSDB->get_Database(&pSDBDatabase);
		BSTR qs = SysAllocString(L"Author='Berio, Adolfo'");
		IDispatch *pIDisp;
		pSDBDatabase->QuerySongs(qs, &pIDisp);	
This returns OK but the IDispatch pointer returned from QuerySongs does not seem to be an iterator. Your example calls get_Iterator, is something a c++ iterable object?

I feel I must be very close to the solution. Any suggestions gratefully received.
Best Regards
Dave Plummer
Norwich UK
MMW user since 2008, MMA user since release
Peke
Posts: 17446
Joined: Tue Jun 10, 2003 7:21 pm
Location: Earth
Contact:

Re: Using the COM interface with VS2017 and plain C++

Post by Peke »

Hi,
In any other languages I used I simply ignored definitions like "IDispatch *pIDisp;" and assumed directly "ISDBSongIterator* pSDBIterator" which would result in "something like pSDBDatabase->QuerySongs(qs, &pSDBIterator);"
Best regards,
Peke
MediaMonkey Team lead QA/Tech Support guru
Admin of Free MediaMonkey addon Site HappyMonkeying
Image
Image
Image
How to attach PICTURE/SCREENSHOTS to forum posts
mcow
Posts: 834
Joined: Sun Sep 21, 2008 9:35 pm
Location: Cupertino, California

Re: Using the COM interface with VS2017 and plain C++

Post by mcow »

Dave Plummer, I just wandered back into this forum after a few years away. I saw your question about using IDispatch.

In this Wiki page I wrote some time ago, I have an example of using PyIDispatch.Invoke(), in the OnTrackSkipped() handler.
Honestly, it's been a long time and I don't remember how to interpret what you see there, but maybe that will give you a leg up on using IDispatch.
mcow
Posts: 834
Joined: Sun Sep 21, 2008 9:35 pm
Location: Cupertino, California

Re: Using the COM interface with VS2017 and plain C++

Post by mcow »

Dave Plummer, I have been doing more intensive work with this lately, and created some C++ code for dealing with the COM objects. When you get an IDispatch object, you need to look up the "DISPID" for the method(s) you want to call and then invoke them. This works roughly like (no guarantees this will compile as written):

Code: Select all

	// your code from the earlier post
	ISDBDatabase *pSDBDatabase;
	pSDB->get_Database(&pSDBDatabase);
	BSTR qs = SysAllocString(L"Author='Berio, Adolfo'");
	IDispatch *pIDisp;
	pSDBDatabase->QuerySongs(qs, &pIDisp);

	// what do do next
	HRESULT hr;
	// Repeat the following for each method or property, save the IDs
	wchar_t cname[]=L"EOF";
	DISPID id;
	hr = pIDisp->GetIDsOfNames(IID_NULL, &cname, 1, LOCALE_USER_DEFAULT, &id);
	
	// then, to retrieve this property value:
	DISPPARAMS dp = { NULL, NULL, 0, 0 };
	VARIANT result;
	hr = pIDisp->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
			&dp, &result, NULL, NULL);
	bool eof = result.boolVal;
Method calls use DISPATCH_METHOD instead of _PROPERTYGET, and passing parameters is done via the DISPPARAMS object. Setting properties can also be done but with additional DISPPARAMS setup.

I don't understand why that "working fragment" you posted before works for you, since the CoCreateInstance() method also returns an IDispatch. Anyway, if you're still interested in getting this to work, DM me and I'll share some generic C++ code I've written to create classes that wrap the IDispatch with maybe a little less pain.
Post Reply