After much toil with MSDN documentation, I was finally got this to work. I took the source code to the Track Info plugin and added the following code to the end of CTrackInfoImpl::OpenPage():
HRESULT hr;
LPDISPATCH pDispHTMLDocument = m_Web.GetDocument();
IHTMLDocument *pIHTMLDocument;
pDispHTMLDocument->QueryInterface(IID_IHTMLDocument, (void **)&pIHTMLDocument);
LPDISPATCH pDispScript;
hr = pIHTMLDocument->get_Script(&pDispScript);
// Debug message to show progress.
CWindow msgWindow;
msgWindow.Attach(m_hWnd);
msgWindow.MessageBox(_T("Here"));
DISPID dispid;
OLECHAR *pszFunct = L"SetCMJAutomation";
hr = pDispScript->GetIDsOfNames(IID_NULL, &pszFunct, 1, LOCALE_USER_DEFAULT, &dispid);
DISPPARAMS dispparams;
memset(&dispparams, 0, sizeof dispparams);
dispparams.cArgs = 1;
dispparams.rgvarg = new VARIANT[1];
dispparams.cNamedArgs = 0;
dispparams.rgvarg[0].vt = VT_DISPATCH;
dispparams.rgvarg[0].pdispVal = m_MJDisp;
VARIANT varResult;
hr = pDispScript->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
&dispparams, &varResult, NULL, NULL);
delete[] dispparams.rgvarg;
What this code does does is call SetCMJAutomation() function defined in the script of my Track Info template page, passing it the IDispatch pointer for the CMJAutomation. From there, I can use the full Automation SDK within the track info template!
NOTE: I have not added any error checking yet, and this code may be leaking memory or objects, for all I know, but it proves the concept.
Test Track Info PageThis sample track info page simply lists all the files in Playing Now:
<html>
<body>
<b>Script should show MC's Playing Now list here:</b><p>
<script>
// These lines show the "old way" of making this page work outside of
// of MC either using JHC's MCIO server, or by directly calling MC's
// Automation SDK out-of-process (requires MC 2.1.238 or above
// NOTE: Commented out for Track Info use
//var mcio = new ActiveXObject("MCIOServer.MediaCentreInsideOutServer");
//var mjA = mcio.GetMJAutomationObject(0, 1);
//var mjA = new ActiveXObject("MediaJukebox Application");
var mjA;
// The code I inserted into the Track Info Plugin will call this method,
// passing it an Automation SDK object, which I store in the global mjA.
function SetCMJAutomation(CMJAutomationObj)
{
mjA = CMJAutomationObj;
alert("SetCMJAutomation was called");
var mjCurPlaylistA = mjA.GetCurPlaylist();
var count = mjCurPlaylistA.GetNumberFiles();
for(i = 0; i < count; i++)
{
mjFileA = mjCurPlaylistA.GetFile(i);
document.write(i + ": " + mjFileA.Filename() + "<br>");
}
}
</script>
</body>
</html>
ResultsNow, my main motivation for doing all of this is for performance. I want to use Automation SDK from inside JScript web page on local machine, but iterating through large lists, such as the current Playing Now list is way too slow from an external web page. I thought that by doing it from a Track Info template, it should be much faster since all interprocess communication is eliminated.
It is, indeed, faster, but not nearly as much as I hoped.
Here is the performance I get from using Automation SDK via JavaScript web page to iterate through large CMJFiles collection using three different methods:
Method | Speed |
Use MC Automation directly out of process (new feature of MC 2.1.238) | 80 files/sec |
Use JHC's MediaCenterInsideOut plugin to provide out-of-process access to MC Automation | 160 files/sec |
Use MC Automation inside Track Info template (in-process) | 320 files/sec |
As you can see, getting in-process doubled the speed vs. what I could do before, but 320 files/sec is still prohibitively slow for interactive use. I guess I will have to wait for JRiver to expand the Automation SDK with some of the requests I made previously (see
http://www.musicex.com/cgi-bin/yabb/YaBB.cgi?board=dev;action=display;num=1056513647). This would eliminate my need to iterate through large collections via Automation.
Soundman