I've made an app called Streamling Overlay for streamers to show which track they're currently playing in VirtualDJ on Windows.
To get the data out of VirtualDJ, I use VDJscript in "ONINIT". It writes a bunch of variables into persistent variables and then saves VDJ's settings, so then my app can then read all the variables out from VDJ's settings.xml. It then repeats this every few seconds. It also saves a timestamp as a check that the variables aren't out of date.
This method works. But is there a better way to get data out from VirtualDJ?
The closest I found to what I'm looking for was a thread requesting a "log_to_file" verb for VDJscript, but that was a post to the "wishes" forum in 2015 and had no replies.
I also found an accessibility tool which seems to see when vdjscript uses "show_text" but I can't see a way to do that, or if it would create other problems.
I've considered trying to work out how to write a plugin but Windows C/C++ isn't my forte, and I'm not sure if VirtualDJ is hostile to such plugins? (there seem to be a lot of links to empty pages on VirtualDJ's site for plugins which were meant to show "now playing" information)
I know the common approach to getting the current track is to reduce the "historyDelay" setting and read the last song from the history log files (.m3u or .txt), but my method gives a more responsive display, showing what's actually currently playing even if the DJ goes back and forth between tracks, and can tell when a song stops playing.
If you're curious, my monstrous ONINIT is below. It just takes the "artist_title", "vu_meter_peak" and "is_audible" for both decks (every 2.5s). Note it calls save_config every 2.5 seconds. It works, but I'd rather a better way that doesn't require saving to and reading from settings.xml. Is there another way?
PengoWray
repeat_start 'streamling_loop' 2500ms & set '@$streamling_d1' `deck 1 get_artist_title` & set '@$streamling_d1_vump' `deck 1 get_vu_meter_peak` & set '@$streamling_d1_ia' `deck 1 is_audible` & set '@$streamling_d2' `deck 2 get_artist_title` & set '@$streamling_d2_vump' `deck 2 get_vu_meter_peak` & set '@$streamling_d2_ia' `deck 2 is_audible` & set '@$streamling_clock' `get_clock 24` & save_config
To get the data out of VirtualDJ, I use VDJscript in "ONINIT". It writes a bunch of variables into persistent variables and then saves VDJ's settings, so then my app can then read all the variables out from VDJ's settings.xml. It then repeats this every few seconds. It also saves a timestamp as a check that the variables aren't out of date.
This method works. But is there a better way to get data out from VirtualDJ?
The closest I found to what I'm looking for was a thread requesting a "log_to_file" verb for VDJscript, but that was a post to the "wishes" forum in 2015 and had no replies.
I also found an accessibility tool which seems to see when vdjscript uses "show_text" but I can't see a way to do that, or if it would create other problems.
I've considered trying to work out how to write a plugin but Windows C/C++ isn't my forte, and I'm not sure if VirtualDJ is hostile to such plugins? (there seem to be a lot of links to empty pages on VirtualDJ's site for plugins which were meant to show "now playing" information)
I know the common approach to getting the current track is to reduce the "historyDelay" setting and read the last song from the history log files (.m3u or .txt), but my method gives a more responsive display, showing what's actually currently playing even if the DJ goes back and forth between tracks, and can tell when a song stops playing.
If you're curious, my monstrous ONINIT is below. It just takes the "artist_title", "vu_meter_peak" and "is_audible" for both decks (every 2.5s). Note it calls save_config every 2.5 seconds. It works, but I'd rather a better way that doesn't require saving to and reading from settings.xml. Is there another way?
PengoWray
repeat_start 'streamling_loop' 2500ms & set '@$streamling_d1' `deck 1 get_artist_title` & set '@$streamling_d1_vump' `deck 1 get_vu_meter_peak` & set '@$streamling_d1_ia' `deck 1 is_audible` & set '@$streamling_d2' `deck 2 get_artist_title` & set '@$streamling_d2_vump' `deck 2 get_vu_meter_peak` & set '@$streamling_d2_ia' `deck 2 is_audible` & set '@$streamling_clock' `get_clock 24` & save_config
Posted Thu 06 Apr 23 @ 10:10 pm
VirtualDJ can already show track information on streams without any app or plugin.
Posted Thu 06 Apr 23 @ 11:41 pm
I can write plugins, I understand your problem is trusting users to write the script correctly, but I can't see such a plugin ever being published by atomix, for a broad scope you'd have to have a effect_string to point to the location written to and then you have the same problem as before; trusting user input.
Posted Fri 07 Apr 23 @ 1:48 am
Thanks for the reply Locodog.
Trusting the user isn't the biggest issue. Sure, I'd definitely prefer if the user didn't have to set anything up, it's not too bad: they can copy-paste the code, and if it doesn't run it's not a catastrophe.
The bigger issue is more that I'm spamming the user's settings.xml. It works for me, but ideally the user could choose when to save their settings themselves like normal instead of me taking it over and autosaving every 2 seconds.
If I could use "effect_string" to write to an .ini instead that would still be a big improvement. I can't find clear documentation for effect_string though, so I'm not sure. Can it be used generally or is it just for talking to plugins?
From what I gather from the sample code, a plugin could simply request the info needed straight from the API. I don't really understand the architecture though. If atomix can deny publishing plugins then it's probably not worth going down that path anyway.
Was hoping there was a better way than what I'm doing but if not I'll just stick with it I guess. Let me know if there's something better I could do, but thanks for your help
Trusting the user isn't the biggest issue. Sure, I'd definitely prefer if the user didn't have to set anything up, it's not too bad: they can copy-paste the code, and if it doesn't run it's not a catastrophe.
The bigger issue is more that I'm spamming the user's settings.xml. It works for me, but ideally the user could choose when to save their settings themselves like normal instead of me taking it over and autosaving every 2 seconds.
If I could use "effect_string" to write to an .ini instead that would still be a big improvement. I can't find clear documentation for effect_string though, so I'm not sure. Can it be used generally or is it just for talking to plugins?
From what I gather from the sample code, a plugin could simply request the info needed straight from the API. I don't really understand the architecture though. If atomix can deny publishing plugins then it's probably not worth going down that path anyway.
Was hoping there was a better way than what I'm doing but if not I'll just stick with it I guess. Let me know if there's something better I could do, but thanks for your help
Posted Fri 07 Apr 23 @ 2:48 am
The API could do that easily, If you're not too hot with c++ then you could make every 30th call to onProcessSamples() grab the information of the master deck and then write it to a file. [instead of having a separate thread plugin]
Atomix might say no to the plugin but you're sharing off site anyway, nothing stopping you there, there's no program gatekeeping / approved list.
writing to a txt file is a few lines once you have the plugin framework built
Action being, maybe,
deck master get_artist_title
the basics of building a plugin are covered here at an accessible level,
https://www.virtualdj.com/forums/249292/VirtualDJ_Plugins/Process_to_generate__dll_for_PC.html
Atomix might say no to the plugin but you're sharing off site anyway, nothing stopping you there, there's no program gatekeeping / approved list.
writing to a txt file is a few lines once you have the plugin framework built
#include <fstream>
...
//as a global private variable
int limiter = 0;
...
//inside onprocesssamples()
// limited to 30th call
if ( limiter == 30 ) {
limiter = 0;
char grabbedInfo[128] = {'\0'};
GetStringInfo("VDJ ACTION TO GRAB INFO", &grabbedInfo[0], 128);
std::ofstream ofs("YOURTXTFILELOCATION.txt", std::ofstream::trunc);
ofs << grabbedInfo;
ofs.close();
}
else limiter++;
Action being, maybe,
deck master get_artist_title
the basics of building a plugin are covered here at an accessible level,
https://www.virtualdj.com/forums/249292/VirtualDJ_Plugins/Process_to_generate__dll_for_PC.html
Posted Fri 07 Apr 23 @ 3:57 am
That's awesome! Thanks heaps. It's been a while since I touched C or C++, but I'll see how I go. Having a starting point helps a lot. Cheers!
Posted Fri 07 Apr 23 @ 4:18 am