Author Topic: Yet Another Remote Control Thread  (Read 574 times)

Jace

  • Posts: 841
Yet Another Remote Control Thread
« on: 15 Sep '21 - 02:40 »
I could've necroed a thread from 5+ years ago or hijacked another adjacent but actually not entirely relevant thread, so here goes.

Is there a convenient way to control XMPlay from another computer these days?

I've had a look at the somewhat recent XMPlay Web (and Android) Remote Control, but the webpage has a syntax error on the javascripts. And the android app also says something's broken when trying to install it. (Also no source to base things on, that I could find)

Also, there's the xmp-remcon from five years back (updated for XMPlay 3.8.2). It shows up in available plugins list, but can't add it to the loaded plugins list, nor figure out how to actually poke at it.



But what I'm actually looking for isn't (probably) all that complicated.

Would just like to have a way to add a file from playlist (or library) to queue, either with playlist/library position number or filename, though can adjust things to pick the track in any other more convenient way.

Is that doable with currently existing plugins/methods or do I need to (re)learn programming to come up with something workable?

I have already tried an external .exe made to  send DDE commands to XMPlay, but can't figure out a way to call it from a web server in a way that it would be able to control XMPlay (running on a different user and so on. Even PsExec or similar isn't able to send the DDE to the player)

Would be extra nice if it could be done without bringing player/playlist into focus.

Ian @ un4seen

  • Administrator
  • Posts: 23983
Re: Yet Another Remote Control Thread
« Reply #1 on: 15 Sep '21 - 16:56 »
The old xmp-remcon plugin should still be working. At least it was here when I tried it just now (with the latest XMPlay version). Perhaps you already have something else running on port 80? If so, you could change the port that xmp-remcon uses in its source code (see "BIND_PORT").

Note it plays files from the playlist/library rather than just queuing them. I haven't tried myself, but it should be possible to get it to queue instead by changing the SendMessageTimeout calls to send 374 ("List track - Queue") instead of 372 ("List track - Play") in the source code.

Jace

  • Posts: 841
Re: Yet Another Remote Control Thread
« Reply #2 on: 15 Sep '21 - 22:07 »
Indeed I do have something on 80.

Well, time to dig out some kinda compiler and wish me luck that I'll get it to work.

Ian @ un4seen

  • Administrator
  • Posts: 23983
Re: Yet Another Remote Control Thread
« Reply #3 on: 16 Sep '21 - 16:38 »
Here's a little update with a custom port option for you to try:

   www.un4seen.com/stuff/xmp-remcon.zip

Add this to your XMPLAY.INI file:

Code: [Select]
[remcon]
port=<number>

Jace

  • Posts: 841
Re: Yet Another Remote Control Thread
« Reply #4 on: 16 Sep '21 - 18:22 »
Does help with getting it to load, yes!
Though took me a moment to realise I need to have the playlist open for the play buttons to work :P

Haven't found a compiler that'll compile it without errors yet, so search continues so I can do the queue tweak thing too

Jace

  • Posts: 841
Re: Yet Another Remote Control Thread
« Reply #5 on: 17 Sep '21 - 01:49 »
I give up.

Have tried with G++, VS 2019, VS 2008, can't get it to compile without errors. And when I've "fixed" the bits that cause errors, it compiles into a dll XMPlay can't even recognise.

Any chance of sharing the whole project thing and letting me know what to use to compile it to get it to work?

Ian @ un4seen

  • Administrator
  • Posts: 23983
Re: Yet Another Remote Control Thread
« Reply #6 on: 17 Sep '21 - 13:56 »
I used an old MinGW/g++ to build the update above. A makefile was also added for that. It should build with any MinGW version but note that more recent versions use libgcc and libstdc++ rather than MS's standard libraries, so you will need to either include those DLLs with the plugin or use the "-static-libgcc -static-libstdc++" options (in the makefile) to link them into the plugin. I would suggest doing the latter.

edit: I've now added a Visual Studio project to the ZIP above.
« Last Edit: 17 Sep '21 - 14:29 by Ian @ un4seen »

Jace

  • Posts: 841
Re: Yet Another Remote Control Thread
« Reply #7 on: 21 Sep '21 - 22:56 »
After a busy weekend, snagged the oldest G++ offered by cygwin (7.4.0), the output's basically the same as with VS and newer G++s

Code: [Select]
xmp-remcon.cpp:49:24: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
 static char *dspname = "XMPlay Remote Control";
                        ^~~~~~~~~~~~~~~~~~~~~~~
xmp-remcon.cpp: In function ‘void cmdCurList(std::string&, char*)’:
xmp-remcon.cpp:106:116: error: cannot convert ‘LPDWORD {aka unsigned int*}’ to ‘PDWORD_PTR {aka long long unsigned int*}’ for argument ‘7’ to ‘LRESULT SendMessageTimeoutW(HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR)’
  if (!SendMessageTimeoutW(XMPlayHWND, WM_WA_IPC, 0, IPC_GETLISTLENGTH, SMTO_ABORTIFHUNG, 300, (LPDWORD)&iNumEntries)) return;
                                                                                                                    ^
xmp-remcon.cpp:109:116: error: cannot convert ‘LPDWORD {aka unsigned int*}’ to ‘PDWORD_PTR {aka long long unsigned int*}’ for argument ‘7’ to ‘LRESULT SendMessageTimeoutW(HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR)’
   if (!SendMessageTimeoutW(XMPlayHWND, WM_WA_IPC, i, IPC_GETPLAYLISTFILE, SMTO_ABORTIFHUNG, 300, (LPDWORD)&pcu8File) || !pcu8File) return;
                                                                                                                    ^
xmp-remcon.cpp:110:118: error: cannot convert ‘LPDWORD {aka unsigned int*}’ to ‘PDWORD_PTR {aka long long unsigned int*}’ for argument ‘7’ to ‘LRESULT SendMessageTimeoutW(HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR)’
   if (!SendMessageTimeoutW(XMPlayHWND, WM_WA_IPC, i, IPC_GETPLAYLISTTITLE, SMTO_ABORTIFHUNG, 300, (LPDWORD)&pcu8Title) || !pcu8Title) return;
                                                                                                                      ^
xmp-remcon.cpp: In function ‘DWORD ThreadProc(LPVOID)’:
xmp-remcon.cpp:161:52: error: cannot convert ‘long unsigned int*’ to ‘__ms_u_long* {aka unsigned int*}’ for argument ‘3’ to ‘int ioctlsocket(SOCKET, int, __ms_u_long*)’
   ioctlsocket(AcceptSocket, ul, (unsigned long*)&ul);
                                                    ^
xmp-remcon.cpp: In function ‘void ReadXMPLibrary()’:
xmp-remcon.cpp:200:16: error: ‘_wfopen’ was not declared in this scope
  FILE *pfLib = _wfopen(wcXMPlayLib, L"rb");
                ^~~~~~~
xmp-remcon.cpp:200:16: note: suggested alternative: ‘fopen’
  FILE *pfLib = _wfopen(wcXMPlayLib, L"rb");
                ^~~~~~~
                fopen
xmp-remcon.cpp:203:15: error: aggregate ‘ReadXMPLibrary()::_stat st’ has incomplete type and cannot be defined
  struct _stat st;
               ^~
xmp-remcon.cpp:204:2: error: ‘_fstat’ was not declared in this scope
  _fstat(fileno(pfLib), &st);
  ^~~~~~
xmp-remcon.cpp:204:2: note: suggested alternative: ‘_stat’
  _fstat(fileno(pfLib), &st);
  ^~~~~~
  _stat

What am I dumbing on and why am I seemingly the only person in the world who can't get this to work? :\

I mean, it would be trivial for you to push a dll out for me with queues instead of direct playbacks. But would be nice if I could update it myself if stuff like a command to dde a list the queued songs (like the playlist view works?) in the future :/

Ian @ un4seen

  • Administrator
  • Posts: 23983
Re: Yet Another Remote Control Thread
« Reply #8 on: 22 Sep '21 - 12:23 »
That looks like you're using a 64-bit version of g++. If so, you can use the "-m32" option to compile for 32-bit instead.

The MinGW/g++ version that I was using is actually much older than that (2.95.3). I'm not sure if it's still available for download. If you already have Visual Studio installed, that would probably be the easiest way to build the plugin. The project that I added earlier was using the Windows 7 SDK but I've changed that now to use the default, so you don't need to bother install the Windows 7 SDK.

saga

  • Posts: 2549
Re: Yet Another Remote Control Thread
« Reply #9 on: 28 Sep '21 - 21:14 »
For anyone potentially running into the same issue as Jace, not having msvcrt.lib (from the xmp-sdk package) in your build path may help getting the plugin to build with Visual Studio. The source code also doesn't compile in strict standard conformance mode due to a missing "const" keyword on line 49 (should be placed right after "static"). This is the same as the first G++ error seen above.

Jace

  • Posts: 841
Re: Yet Another Remote Control Thread
« Reply #10 on: 28 Sep '21 - 21:37 »
Yeah, thanks to Saga I was able to actually compile it.

The thing I've been trying to do with this is a music player on twitch.tv but where you have a full control of the playlist, and people can request/queue any song on it. As it is, it'll work perfectly enough, but wondering if there could be a DDE call to get the current queue list. It's currently kinda available with the playlist panel (in show queue mode), but there's no "resize depending on the size of the queue" thing. For my use, just having access to the current queue list ought to fix that with ease.

Jace

  • Posts: 841
Re: Yet Another Remote Control Thread
« Reply #11 on: 28 Sep '21 - 22:15 »
Some weirdness I've experienced (Unsure if relevant, but on a Win7x64 setup), if the last XMPlay-related window active was the playlist, the queue requests work fine. But if the main player was the last XMPlay-related window active, the queue commands won't go through. Any idea how that might make sense?

Ian @ un4seen

  • Administrator
  • Posts: 23983
Re: Yet Another Remote Control Thread
« Reply #12 on: 29 Sep '21 - 17:58 »
The thing I've been trying to do with this is a music player on twitch.tv but where you have a full control of the playlist, and people can request/queue any song on it. As it is, it'll work perfectly enough, but wondering if there could be a DDE call to get the current queue list. It's currently kinda available with the playlist panel (in show queue mode), but there's no "resize depending on the size of the queue" thing. For my use, just having access to the current queue list ought to fix that with ease.

Unfortunately, there isn't currently any way to query the queued tracks, or indeed the playlist or library really. The playlist is currently only available via the supported Winamp API, and the library by reading the XMPLAY.LIBRARY file directly. I have been meaning to add some track/list manipulation functions to the native plugin APIs but the details of that haven't all been worked out yet.

Some weirdness I've experienced (Unsure if relevant, but on a Win7x64 setup), if the last XMPlay-related window active was the playlist, the queue requests work fine. But if the main player was the last XMPlay-related window active, the queue commands won't go through. Any idea how that might make sense?

I think the issue there may be that the "List track" shortcuts (which those SendMessageTimeout calls are accessing) apply to the selected track(s) in the currently active list, and you will need that to be the playlist for the xmp-remcon plugin to work properly. Do you have the queue view (rather than playlist) active in the main window? If so, does switching it back to playlist view prevent the problem?

Jace

  • Posts: 841
Re: Yet Another Remote Control Thread
« Reply #13 on: 29 Sep '21 - 20:30 »
A) Fair enough.

2) Yeah, the main player playlist panel was set to view the queue, as I was planning to use that to show the incoming list and stuff. But making it show the full playlist seems to have sorted that out. Will note down if I happen to run into another thing which makes it not be able to be queued.

Also, I did notice that as a workaround, I could read the playlist file and get the queue list from that. But that doesn't get saved often enough to be reliable for this kinda use. Might see if I can something reliable going on with a program which ran read the RAM space of another program or something to grab the actual live values :P

Edit:
OR... Write any queued track requests into a file and keep an eye on what has been played... Might be easier.

Edit edit:
Okay, writing down file/title into a file on queue and then checking the file when a new file is loaded, removing the top line if current song is the same as the oldest queued item is a passable workaround. Huzzah!
« Last Edit: 30 Sep '21 - 02:00 by Jace »

Jace

  • Posts: 841
Re: Yet Another Remote Control Thread
« Reply #14 on: 24 Nov '21 - 06:13 »
Poking it even further, trying to see if I could include the track length in all the files on playlist. Current test is
Code: [Select]
void cmdCurList(string& resp, char* pcParam)
{
char* pcu8File, * pcu8Title, * pcu8Len;
int iNumEntries;
if (!SendMessageTimeoutW(XMPlayHWND, WM_WA_IPC, 0, IPC_GETLISTLENGTH, SMTO_ABORTIFHUNG, 300, (LPDWORD)&iNumEntries)) return;
for (int i = 0; i < iNumEntries; i++)
{
if (!SendMessageTimeoutW(XMPlayHWND, WM_WA_IPC, i, IPC_GETPLAYLISTFILE, SMTO_ABORTIFHUNG, 300, (LPDWORD)&pcu8File) || !pcu8File) return;
if (!SendMessageTimeoutW(XMPlayHWND, WM_WA_IPC, i, IPC_GETPLAYLISTTITLE, SMTO_ABORTIFHUNG, 300, (LPDWORD)&pcu8Title) || !pcu8Title) return;
pcu8Len = xmpfmisc->GetTag(TAG_LENGTH);
ostringstream o; o << "<a href='/?playlist=" << itos(i) << "'>Play " << itos(i + 1) << "</a>: " << pcu8Title << " (" << pcu8File << ") " << pcu8Len <<  "<br>"; resp += o.str();
}
}
But that (quite obviously, looking at the code) just returns the length of the currently playing track. I tried with
Code: [Select]
IPC_GETOUTPUTTIME as well, but that just crashed XMP when I tried to poke at it.

Am I just being a dumb (and suck at searching) or is there no way to get track length of a playlist entry?

Plan E for Effort is to decode the library and get the lengths from there. Though unsure what to do with playlist entries which haven't shoved themselves onto the library yet

Yeah, that's why you don't try to figure this shit out at 8AM with questionable sleep. The durations are in the playlist file >_>
« Last Edit: 25 Nov '21 - 17:36 by Jace »