1

I am desperately trying to automate BSPlayer from my script. I was successful in sending simple command ids to the BSPlayer window(volume up/down, play/pause, etc.), however I am not able to get the file name back.

Here is the BSPlayer API. I was able to emulate in python the first parts, however the WM_COPYDATA doesn't work.

Here is my Python code:

copyDataCmd = COPYDATASTRUCT()
copyDataCmd.dwData = self.BSP_GetFileName
copyDataCmd.lpData = ""
copyDataCmd.cbData = 4                
win32gui.SendMessage(self.playerWindowHandler, win32con.WM_COPYDATA, 
                     ownHandler, copyDataCmd);

Obviously .lpData returns "" ...

What I am trying to emulate:

cds:TCOPYDATASTRUCT; 
buf:array[0..MAX_PATH-1] of char; 
adr:pointer; // 
adr:=@buf; 
cds.dwData:=BSP_GetFileName; 
cds.lpData:=@adr; 
cds.cbData:=4; 
SendMessage(bsp_hand,WM_COPYDATA,appHWND,lParam(@cds)); 
// available in BSPlayer version 0.84.484+ // 
// appHWND is calling application window handle 
// File name will be copied to buf // 
// Get open file name 
BSP_GetFileName = $1010B;

To be more verbose, I am trying to get the filename from a BSPlayer window. For this I am trying to emulate the code above. I expect a buffer of some sort to be filled with my desired string, but it comes up empty. So, again, I want the Python equivalent of the code just above.

For example this code was emulated succesfully:

status := SendMessage(bsp_hand,WM_BSP_CMD,BSP_GetStatus,0); 
// available in BSPlayer version 0.84.484+ // 
// Return player status // 0 - STOP // 1 - PAUSE 
// 2 - PLAY // 4 - No movie   open        
BSP_GetStatus = $10102; 

Thanks in advance!

Radu
  • 2,076
  • 2
  • 20
  • 40
  • The code you are trying to emulate doesn't work. It cannot work. It is sending to the other process a pointer to a pointer to a buffer. That's one level of indirection too far. You need a sample that works. – David Heffernan Nov 08 '12 at 15:21
  • @DavidHeffernan I was able to emulate another code on that page(see in the question). – Radu Nov 08 '12 at 15:23
  • 1
    The Pascal code needs to assign `@buf` to `lpData` and `MAX_PATH*SizeOf(Char)` to `cbData`. Then it will be marshalled properly. The developers of that piece of code almost certainly only tested in-process. – David Heffernan Nov 08 '12 at 15:29
  • @DavidHeffernan You may be right abouth the first part. However assigning 4 to cbData may be the size of the pointer - which is fixed, only depending on your machine's memory address unit length(probably 4 in their case). – Radu Nov 09 '12 at 12:54
  • I still need a valid Python code, if anyone can help - I appreciate it. I could make 2 windows with 2 different python scripts and see if they communicate, but I fear I'm overcomplicating it. – Radu Nov 09 '12 at 12:55
  • Yes, it is the size of the pointer. But that's the problem. It needs to be the size of a buffer. `WM_COPYDATA` exists to allow data to be marshalled from one process address space to another. You can't marshal a pointer from one process address space to another because it is only meaningful in a single address space. I'm sure you still need some code, but unless you can specify what the code needs to do, I for one cannot help. – David Heffernan Nov 09 '12 at 13:09
  • @DavidHeffernan I did a minor edit of the question, hopefully it is clear for you. I just want to read back from a buffer I allocate somehow in Python the player window's filename - as stated in the BSPlayer API - which according to you may be wrong. – Radu Nov 09 '12 at 13:13
  • 1
    You cannot make that call from a different process. It will work from the same process. So, it's fine for a plugin, but I guess you are not writing a plugin. I guess your code runs in a different process from the `bsp_hand` window. – David Heffernan Nov 09 '12 at 13:21
  • @DavidHeffernan Yes, that is exactly what I am doing. And the BSPlayerAPI specified the plugin. I just ignored it unfortunately. So thank you for your reply - I would mark it as correct if I could! – Radu Nov 09 '12 at 13:23
  • OK, you have an answer saying all that now! – David Heffernan Nov 09 '12 at 13:29

1 Answers1

1

You cannot replicate that WM_COPYDATA in your Python code. It can only be used in-proc, for example for plugins.

The example Delphi code is written under the assumption that the call to WM_COPYDATA is made from the same process as the window which receives the message. That's because the WM_COPYDATA is used to copy a pointer, and pointers are only valid inside the process which allocated the memory. You cannot send a pointer across a process boundary.

In my opinion, the designers of the interface are abusing WM_COPYDATA. It is meant to be used to solve the exact problem of transferring data between processes. It is the simplest most lightweight inter-process communication available. To then use it to transfer a pointer rather defeats the process.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Guess they do abuse it. However to their credit, they did specify it is to be used from a plugin - however I didn't understand it at the time. – Radu Nov 09 '12 at 13:40