Trouble With Handling COM Events
Moderators: Gurus, Addon Administrators
-
- Posts: 18
- Joined: Sun May 27, 2007 4:49 pm
Trouble With Handling COM Events
I'm completely new to COM and I have some experience programming in Python, and for a personal project to improve familiarity in both, and to make something practical with MediaMonkey, I was wondering if someone could help me figure out how to handle events? I've figured out how to change basic stuff, and make automated nodes, but events are a head scratcher for me. Any help would be greatly appreciated.
Re: Trouble With Handling COM Events
What language are you using or are you just using VBScript?
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Melloware Inc.
MonkeyTunes - DACP Server for MediaMonkey
Intelliremote - Take Back Control of your HTPC!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Melloware Inc.
MonkeyTunes - DACP Server for MediaMonkey
Intelliremote - Take Back Control of your HTPC!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- Posts: 18
- Joined: Sun May 27, 2007 4:49 pm
Re: Trouble With Handling COM Events
I'm using Python as the programming/scripting language.
Re: Trouble With Handling COM Events
Well the problem with Events from any "out-of-process" application like Python, .NET, Delphi etc is that they do not seem to register the events. IF you search for it in the forums you will see nothing but problems with the Events not working outside of an "in-process" call.SpiderMonkey wrote:I'm using Python as the programming/scripting language.
The only way I have seen it solved is in .NET by using a COM object and registering that COM object of your out of process app in MM itself.
See this thread: http://www.mediamonkey.com/forum/viewto ... nts#p69933
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Melloware Inc.
MonkeyTunes - DACP Server for MediaMonkey
Intelliremote - Take Back Control of your HTPC!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Melloware Inc.
MonkeyTunes - DACP Server for MediaMonkey
Intelliremote - Take Back Control of your HTPC!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- Posts: 18
- Joined: Sun May 27, 2007 4:49 pm
Re: Trouble With Handling COM Events
@Melloware: I wish I knew what to look for since I'm not familiar with .Net. Maybe you can explain it?
@Anyone with Python Experience/COM Handling:
This is the code I'm using to get the COM Object.
I can use some methods and get some information...
...and I can pause the player and control it, etc.
Also, if I want to find out exactly what will fire when the external process searches for events, I can even find that out.
Basically, it knows what classes are going to execute when an event is called. But I don't know of a way to get the external process to tell when the class executes. After some online searches, I figured I could use a "while" loop but I wouldn't know what to check for.
I know the simple solution would just be to do everything in VBS. From using a helper script to launch the python file, to maybe having VBS handle the events and then make calls to the python script, but I wouldn't know how to start doing that too. Hmmm... I'll still think about it...
@Anyone with Python Experience/COM Handling:
This is the code I'm using to get the COM Object.
Code: Select all
import win32com.client
SDB = win32com.client.Dispatch("SongsDB.SDBApplication")
Code: Select all
>>> SDB.Player.isPlaying
True
>>>SDB.Player.Pause
Also, if I want to find out exactly what will fire when the external process searches for events, I can even find that out.
Code: Select all
>>> events = win32com.client.getevents("SongsDB.SDBApplication")
>>> events
<class win32com.gen_py.E602ED16-8EF9-4F08-B09F-6F6E8306C51Bx0x1x0.ISDBApplicationEvents at 0x02055FC0>
I know the simple solution would just be to do everything in VBS. From using a helper script to launch the python file, to maybe having VBS handle the events and then make calls to the python script, but I wouldn't know how to start doing that too. Hmmm... I'll still think about it...
-
- Posts: 931
- Joined: Fri Jul 10, 2009 8:10 am
Re: Trouble With Handling COM Events
I'm sure that you can achieve what you need with Python but you're definitely going to be in the minority. I've used both VBScript and Delphi to interface to MM quite extensively now. I'd suggest learning VBS - it's actually simpler than Python and most tasks can be achieved with little more than Notepad to edit the files.
During my Delphi work I autogenerated an MM type library from the executable (fragment attached) which shows the interface exposed by MM through the COM interface.
Of course this will not help with your solution but it does show the interface in a source-code manner.
Regards
Mark
During my Delphi work I autogenerated an MM type library from the executable (fragment attached) which shows the interface exposed by MM through the COM interface.
Code: Select all
// *********************************************************************//
// Interface: ISDBApplication
// Flags: (4416) Dual OleAutomation Dispatchable
// GUID: {1FAF02F8-A7D3-41F1-9210-A3B12046F136}
// *********************************************************************//
ISDBApplication = interface(IDispatch)
['{1FAF02F8-A7D3-41F1-9210-A3B12046F136}']
function Get_VersionString: WideString; safecall;
function Get_CurrentSongList: ISDBSongList; safecall;
function Get_SelectedSongList: ISDBSongList; safecall;
function Get_Player: ISDBPlayer; safecall;
function Get_IniFile: ISDBIniFile; safecall;
function Get_VersionHi: Integer; safecall;
function Get_VersionLo: Integer; safecall;
function Get_Database: ISDBDatabase; safecall;
function MessageBox(const MessageText: WideString; MsgType: EnumMsgBox; Buttons: OleVariant): Integer; safecall;
function Get_VersionRelease: Integer; safecall;
function Get_Progress: ISDBProgress; safecall;
function Get_CommonDialog: ISDBCommonDialog; safecall;
function Get_AllVisibleSongList: ISDBSongList; safecall;
function Localize(const Value: WideString): WideString; safecall;
function toASCII(const Value: WideString): WideString; safecall;
function Get_PlaylistByTitle(const Title: WideString): ISDBPlaylist; safecall;
function Get_MainTree: ISDBTree; safecall;
function Get_MainTracksWindow: ISDBTracksWindow; safecall;
function Get_ShutdownAfterDisconnect: WordBool; safecall;
procedure Set_ShutdownAfterDisconnect(Value: WordBool); safecall;
function Get_IsRunning: WordBool; safecall;
function Get_UI: ISDBUI; safecall;
function Get_Registry: ISDBRegistry; safecall;
function Get_Objects(const Name: WideString): IDispatch; safecall;
procedure Set_Objects(const Name: WideString; const Value: IDispatch); safecall;
function RegisterIcon(const Filename: WideString; IconType: Integer): Integer; safecall;
function Get_NewSongData: ISDBSongData; safecall;
function Get_Device: SDBDevice; safecall;
function Get_ApplicationPath: WideString; safecall;
function Get_MyMusicPath: WideString; safecall;
function Get_Tools: ISDBTools; safecall;
function Get_NewSongList: ISDBSongList; safecall;
function Format(const Text: WideString; Param1: OleVariant; Param2: OleVariant;
Param3: OleVariant): WideString; safecall;
function LocalizedFormat(const Text: WideString; Param1: OleVariant; Param2: OleVariant;
Param3: OleVariant): WideString; safecall;
function SelectFolder(const Folder: WideString; const ShowText: WideString): WideString; safecall;
function Get_TemporaryFolder: WideString; safecall;
procedure ProcessMessages; safecall;
function RegisterIconHandle(IconHandle: Integer; IconType: Integer): Integer; safecall;
function CreateTimer(Interval: Integer): ISDBTimer; safecall;
function Get_WebControl: IDispatch; safecall;
function LocalizeGen(const LangFile: WideString; const Value: WideString): WideString; safecall;
function Get_CursorType: Integer; safecall;
procedure Set_CursorType(Value: Integer); safecall;
function Get_NewStringList: ISDBStringList; safecall;
procedure RefreshScriptItems; safecall;
function IsKnownFileType(const Filename: WideString): WordBool; safecall;
function Get_IconsPath: WideString; safecall;
function Get_EqualizerPath: WideString; safecall;
function Get_SkinsPath: WideString; safecall;
function Get_PluginsPath: WideString; safecall;
function Get_ScriptsPath: WideString; safecall;
function Get_VersionBuild: Integer; safecall;
function Get_ComServerUIActive: WordBool; safecall;
procedure Set_ComServerUIActive(Value: WordBool); safecall;
property VersionString: WideString read Get_VersionString;
property CurrentSongList: ISDBSongList read Get_CurrentSongList;
property SelectedSongList: ISDBSongList read Get_SelectedSongList;
property Player: ISDBPlayer read Get_Player;
property IniFile: ISDBIniFile read Get_IniFile;
property VersionHi: Integer read Get_VersionHi;
property VersionLo: Integer read Get_VersionLo;
property Database: ISDBDatabase read Get_Database;
property VersionRelease: Integer read Get_VersionRelease;
property Progress: ISDBProgress read Get_Progress;
property CommonDialog: ISDBCommonDialog read Get_CommonDialog;
property AllVisibleSongList: ISDBSongList read Get_AllVisibleSongList;
property PlaylistByTitle[const Title: WideString]: ISDBPlaylist read Get_PlaylistByTitle;
property MainTree: ISDBTree read Get_MainTree;
property MainTracksWindow: ISDBTracksWindow read Get_MainTracksWindow;
property ShutdownAfterDisconnect: WordBool read Get_ShutdownAfterDisconnect write Set_ShutdownAfterDisconnect;
property IsRunning: WordBool read Get_IsRunning;
property UI: ISDBUI read Get_UI;
property Registry: ISDBRegistry read Get_Registry;
property Objects[const Name: WideString]: IDispatch read Get_Objects write Set_Objects;
property NewSongData: ISDBSongData read Get_NewSongData;
property Device: SDBDevice read Get_Device;
property ApplicationPath: WideString read Get_ApplicationPath;
property MyMusicPath: WideString read Get_MyMusicPath;
property Tools: ISDBTools read Get_Tools;
property NewSongList: ISDBSongList read Get_NewSongList;
property TemporaryFolder: WideString read Get_TemporaryFolder;
property WebControl: IDispatch read Get_WebControl;
property CursorType: Integer read Get_CursorType write Set_CursorType;
property NewStringList: ISDBStringList read Get_NewStringList;
property IconsPath: WideString read Get_IconsPath;
property EqualizerPath: WideString read Get_EqualizerPath;
property SkinsPath: WideString read Get_SkinsPath;
property PluginsPath: WideString read Get_PluginsPath;
property ScriptsPath: WideString read Get_ScriptsPath;
property VersionBuild: Integer read Get_VersionBuild;
property ComServerUIActive: WordBool read Get_ComServerUIActive write Set_ComServerUIActive;
end;
Regards
Mark
Windows 7,8 / Ubuntu 13.10 / Mavericks 10.9 / iOS 7.1 / iTunes 11.1
iTunes plugin (d_itunes & itunes4) http://www.mediamonkey.com/forum/viewto ... =2&t=45713
Running MM under Mac OS X with Wine http://www.mediamonkey.com/forum/viewto ... =4&t=58507
iTunes plugin (d_itunes & itunes4) http://www.mediamonkey.com/forum/viewto ... =2&t=45713
Running MM under Mac OS X with Wine http://www.mediamonkey.com/forum/viewto ... =4&t=58507
Re: Trouble With Handling COM Events
I agree with Mark on this one. However even when using Delphi and COM I was never able to get the events to fire in my code.
The only way I was able to accomplish that is by using a combination of VBS to actually initialize my code with the SongsDB object and register the events.
The only way I was able to accomplish that is by using a combination of VBS to actually initialize my code with the SongsDB object and register the events.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Melloware Inc.
MonkeyTunes - DACP Server for MediaMonkey
Intelliremote - Take Back Control of your HTPC!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Melloware Inc.
MonkeyTunes - DACP Server for MediaMonkey
Intelliremote - Take Back Control of your HTPC!
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- Posts: 931
- Joined: Fri Jul 10, 2009 8:10 am
Re: Trouble With Handling COM Events
The device driver (Delphi) used events to trap the tree node expansion/contraction. I know the code works but I only modified it to my own needs so can't take all the credit.
Here is a few snippets ...
Mark
Here is a few snippets ...
Code: Select all
procedure AddNodes( Node:Variant; Start:boolean);
var
Tree, NewNode : Variant;
FConnectionToken : Longint;
begin
if Start then
begin
Tree := MMInterf.MainTree;
if ShowLibraryNode then
begin
NewNode := Tree.CreateNode;
NewNode.Caption := MMInterf.Localize( 'Library');
NewNode.SortCriteria := -1000;
NewNode.IconIndex := 19; // Library icon
NewNode.CustomNodeId := NODE_LIBRARY;
if TreeEvents=nil then
TreeEvents := TNodesEventSink.Create;
InterfaceConnect( NewNode, DIID_ISDBTreeNodeEvents, TreeEvents, FConnectionToken);
Tree.AddNode( Node, NewNode, 3);
NewNode.HasChildren := True;
NewNode := Tree.CreateNode;
NewNode.Caption := MMInterf.Localize( 'Playlists');
NewNode.SortCriteria := -1000;
NewNode.IconIndex := 19; // Library icon
NewNode.CustomNodeId := NODE_PLAYLISTS;
if TreeEvents=nil then
TreeEvents := TNodesEventSink.Create;
InterfaceConnect( NewNode, DIID_ISDBTreeNodeEvents, TreeEvents, FConnectionToken);
Tree.AddNode( Node, NewNode, 3);
NewNode.HasChildren := True;
end;
end;
end;
function TNodesEventSink.Invoke(DispID: Integer; const IID: TGUID;
LocaleID: Integer; Flags: Word; var Params; VarResult, ExcepInfo,
ArgErr: Pointer): HResult;
begin
Result := S_OK;
case DispID of
201: OnNodeChildren( Variant(TDispParams(Params).rgvarg^[0]));
202: OnNodeTracks( Variant(TDispParams(Params).rgvarg^[0]));
end;
end;
Windows 7,8 / Ubuntu 13.10 / Mavericks 10.9 / iOS 7.1 / iTunes 11.1
iTunes plugin (d_itunes & itunes4) http://www.mediamonkey.com/forum/viewto ... =2&t=45713
Running MM under Mac OS X with Wine http://www.mediamonkey.com/forum/viewto ... =4&t=58507
iTunes plugin (d_itunes & itunes4) http://www.mediamonkey.com/forum/viewto ... =2&t=45713
Running MM under Mac OS X with Wine http://www.mediamonkey.com/forum/viewto ... =4&t=58507
-
- Posts: 18
- Joined: Sun May 27, 2007 4:49 pm
Re: Trouble With Handling COM Events
Mark,
is that your delphi script (snippet) for handling events? Mine going over it if it is?
is that your delphi script (snippet) for handling events? Mine going over it if it is?
Re: Trouble With Handling COM Events
I'm working on the same issue that spidermonkey was: I have an externally-started Python script that I want to respond to events from MediaMonkey.
I found an interesting bit of sample code, Python hooking into an event-generating COM object, at http://web.mit.edu/zacka/Public/wallcom ... /speech.py.
What I got from that code:
win32com.client.getevents() returns an event-handler class object, whose methods are the event handlers. That code implements a subclass that overrides the desired event handler method.
In order to process the events, there needs to be a loop (which you probably want in a background thread) calling pythoncom.PumpWaitingMessages(). In the example code, the subclassed event handler is instantiated with this interesting comment:
So I've tried a similar thing with MediaMonkey, but with no success yet. I can define and instantiate a subclass, but I haven't yet seen the event fire. It's not clear whether the script object's RegisterEvent() should be used in this case, and if it is, it's not clear which method name I should be passing to it.
Maybe the Script object is the one that's running the PumpWaitingMessages() loop in MediaMonkey.
If the script object is necessary, you can get to it using this: I guess that's a global object, not specific to a given script.
What would be great is for the Script object to support hooking directly into a subclass of the getevents() object.
I found an interesting bit of sample code, Python hooking into an event-generating COM object, at http://web.mit.edu/zacka/Public/wallcom ... /speech.py.
What I got from that code:
win32com.client.getevents() returns an event-handler class object, whose methods are the event handlers. That code implements a subclass that overrides the desired event handler method.
In order to process the events, there needs to be a loop (which you probably want in a background thread) calling pythoncom.PumpWaitingMessages(). In the example code, the subclassed event handler is instantiated with this interesting comment:
Code: Select all
# Just creating a _ListenerCallback object makes events
# fire till listener loses reference to its grammar object
_ListenerCallback(context, listener, callback)
Maybe the Script object is the one that's running the PumpWaitingMessages() loop in MediaMonkey.
If the script object is necessary, you can get to it using this:
Code: Select all
win32com.client.Dispatch('SongsDB.SDBScriptControl')
What would be great is for the Script object to support hooking directly into a subclass of the getevents() object.