I'm looking for partners in development of a new plugin. The plugin will be named InstruLitez.

The concept of the final working visualization plugin is very similar to "DiscoLitez v2.1 Standard" what I used with it's own circuit (DiscoLitez Deluxe 32), but now I have a notebook and I don't have LPT port what this circuit requires. No, LPT->USB converters don't work.

After a long period of time spent on trying to get DiscoLitez working on USB with no success, I decided to buy a new circuit called PACLed64.

In the opposite of DLitez (32 output / 2 state: ON-OFF for each LED), it can handle 64 channels with 255 level of brightness for each channel. It comes with it's test program and the LEDBlinky software is compatible with it too. In LEDBlinky I can set up something similar that I want, but it picks the audio signal from the MIC Input and not that configurable as the DLitez Plugin.

So what I want from InstruLitez?
When visualization starts it shows the 64 channels in table form with each channels actual state (like in DLitez :P ) and when I click on a channel it shows a config dialog for the actual channel where I can set-up when the LED should be lighted on.

Since PACLed can adjust the level of brightness it would be great if this option could be used (think RGB LEDs and color mixing, the circuit is planned mainly for this).

Unfortunately I've just started to learn programming for about two weeks ago and started in C# what I changed to C++ when this project came to my mind. If someone interrested in this project and want to help please don't turn your back on me because my "unknowledge" in programming: Trust me, I can learn lightning fast! Just help!

The PACLed64 has a good SDK (sources in C++ included too) and it contains the .DLL (driver) for the device, so I think communicating and flashing the leds will be the easiest and the last period of programming what I think I can do alone. So somebody who wants to help me and don't have the circuit does not need to worry about how to help with hardware related things.

I mainly need help in a GUI which contains a spectrum analyzer (yes again, like in DLitez) and the actual state of the channels. I know about spectrumData and waveformdata arrays and I can imagine the main working method cycle but yet now I don't have the programming experience to do that alone.

Finally if somebody is interrested please feel free to concact me here or by PM and sorry for my bad english.

I want to make a whole new particular program, where there will be several ways to control the leds and winamp music visualization will be just an option. If the user dont want to use it he/she just dont need to install and start WinAmp.

Anyway thank for reply, this was my first idea (just making a vis plugin).
If I cant get it work, i will make my prog without winamp option and make a vis plugin particulalry.

The IPC message you referenced earlier doesn't return a pointer to the data. It returns a pointer to a function that returns the data. I don't know how but you would need to be able to get Winamp to call the function and store its return value into Winamp's memory space, then retrieve the data with ReadProcessMemory. How to do that I have no clue at the moment.

Thanks for the answer. It is a good feel, that somebody reacts to my problem.

Yes already realized that IPC_GETSADATAFUNC works only in WinAmp. This can be used, when somebody writes a plugin which is not visualization or DSP (eg. General Purpose) and want to retrieve spectrumdata.

It's a very complicated multi-part process and it's a bit of a hack that relies on certain assumptions about DLL load order.

I wrote a Borland VCL application to load a pre-named DLL into an already running Winamp instance. Here's the source:

code:HWND parent=::FindWindow("Winamp v1.x",NULL);
if(IsWindow(parent))
{
AnsiString Dll=Application->ExeName; //this is just a quick way to find the exact path and name of my dll
Dll=ExpandFileName(Dll); //same as above
Dll=ExtractFilePath(Dll); //same as above
Dll=IncludeTrailingBackslash(Dll); //same as above
Dll=Dll+"WinampInjector.dll"; //same as above
HMODULE mod=::GetModuleHandle(TEXT("kernel32.dll")); //OS library that contains the LoadLibraryA function
if(mod==NULL){mod=::GetModuleHandle(TEXT("kernel.dll"));} //I don't think this one is needed but just in case...
FARPROC arf=::GetProcAddress(mod,TEXT("LoadLibraryA")); //this assumes that the proc address is the same in the remote application as the local, this is the hacky part.
DWORD ProcID=0;
DWORD ThreadID=::GetWindowThreadProcessId(parent,&ProcID);
HANDLE hProc=::OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcID);
LPVOID a=::VirtualAllocEx( //this (supposedly) will allocate a safe area of memory in the remote app to store the ansi full name and path to the DLL I want to load.
hProc,
NULL,
Dll.Length()+1,
MEM_COMMIT|MEM_TOP_DOWN,
PAGE_READWRITE
);
::WriteProcessMemory( //this will copy from my locally stored DLL file&path to the remote address area previously allocated by the above call to VirtualAllocEx
hProc,
a,
Dll.c_str(),
Dll.Length()+1,
NULL
);
HANDLE hThread=::CreateRemoteThread(hProc,NULL,0,(LPTHREAD_START_ROUTINE)arf,(void *)a,CREATE_SUSPENDED,&ThreadID); //The hacky hackyness of hack, this tells Windows to create a new thread in the remote process with a start address of LoadLibraryA with the parameter set to the remote memory allocated by VirtualAllocEx
::ResumeThread(hThread);
::CloseHandle(hThread);
::CloseHandle(hProc);
}

Whoever did that, please undo it. Yes, it's superspaced but at least the [CODE][/CODE] tags let the text flow with proper spacing and doesn't utterly annihilate the indentations that make it easier to read.

I know you're trying to help and it's appreciated, 'cept this time. lol

Attached in this post is an unsigned exe and dll combo that will get the SA data on a Timer pulsing a named Event object that holds a thread to re-call the export_sa_get function. The actual SA data address (and Winamp parent window handle) are transmitted to the EXE by a RegisterWindowMessage when the DLL is first remotely loaded into an already running instance of Winamp.

I had a feeling it wouldn't work on Win7 64 bit. Since the last post I've refined the DLL and EXE a bit though I doubt it will make a difference on Win7 64bit, you can still try though. Yes, I can attach source, but remember, this is a Borland VCL based project so it will never compile as-is in MSVC.

I'm also thinking another way you can get Windows to load a DLL to a external app would be to install a specially crafted hook DLL into it.

[EDIT /]
Since it didn't work for you on Win7 64 bit I made a video to show it working on WinXP 32 bit.

Yes, the second version also freezes, i think its because 64bit. When I click the button it only shows the first frame of spectrum analizator and from that point when I click WinAmp it starts "no-replying" and freezes.

I can show it to you, what you say for a teamviewer presentation?

My girlfriend's brother is my co-worker on this project and he has a degree in programming. He studied Borland C++ and Delphi at University. It doesn't matter I don't understand some code, he may will.

Anyway thanks for this awesome attachment, your work and waiting for your reply.

/EDIT:
I will try it on a WinXP 32bit machine (my old comp.) as soon as possible ...

stupid question but you are building it as a 32-bit compile? as a 64bit version is very much likely to do what you are seeing. though really trying to remote load things into Winamp is going to be risky and more likely to fail as you're finding and is why most people end up just doing a native plug-in dll and then have that off-load data to the remote process as needed.

Ah, ok, then it's probably freezing Winamp at the FreeLibraryAndExitThread call after the SendMessageAsync that lets the main app know the memory location and window handle to the Winamp instance. On DLL process attach it finds the Winamp functions, calls them to find the mem loc, creates a named event for the main app to control, then spawns another thread of execution to handle the event. The functions have to be continuously called to refresh the spectrum eq data so that's the reason to keep the DLL loaded for the duration of the data grab. I'll see if I can recompile a version that doesn't need to call FreeLibraryAndExitThread to prep an unload of itself when it's no longer needed.

Quote:

Originally Posted by DrO

stupid question but you are building it as a 32-bit compile?...

Nope, not a stupid question. My old Borland compiler doesn't support 64 bit compiles. I can only do 32 bit compiles. When things die on a 64 bit machine I just chalk it up to Microsoft usually not creating a truly backward compatible OS, and since Winamp itself is still 32 bit I don't see why I should be forced to compile to 64 bit to grab data from a 32 bit application anyways.

Quote:

Originally Posted by DrO

...why most people end up just doing a native plug-in dll and then have that off-load data to the remote process as needed.

I agree and have already suggested as much. However the topic is about getting the data without making a Winamp plugin. I consider it a challenge!

No, I thought for a plugin plus main app combination. But I am also happy with your "pluginless" idea.

Crap! I must've mis-read what you wrote.

Actually, making a plugin would be easier. You would need to include the IPC header and VIS header files into your project (from the Winamp Plugin SDK download), provide the appropriate export functions, the appropriate vis struct, and go from there. You wouldn't need to worry about using hacks to remotely load a DLL into Winamp and you could get more data from a vis plugin anyways.

A while back when I wrote a hook DLL for keyboard shortcut hooking and other things for an equipment controller I used a shared memory object to pass larger amounts of information between applications. I had previously looked at named pipes and concluded it wouldn't work for my application for some reason I've already forgotten. With this one I'm just using a named event to trigger the export_sa_whatever function calling and then using ReadProcessMemory (from the main app) to get the data directly without duplicating it.

Oops, found technical and coding issues that may have been the real culprit (reading 40 bytes from a 39 byte memory space, oops) and was not freeing the named event when unloaded because of an oversight on my part. See if this one works better.