Old 1st October 2013, 04:10   #1
Ghantu
Junior Member
 
Join Date: Oct 2013
Posts: 3
Persistent storage, threading

Hey there!

I'm working on creating a plugin for the first time and so far it's going okay. I managed to convert the "gen_myplugin" example code on the wiki into a media library plugin and get it to pop up dialog boxes on init and quit, so I'm feeling pretty good, and now I'm poking through the SDK to see how this stuff works. I had two questions though:

First, is there convenient persistent storage for plugins? I'm not looking for a lot of space, just some config strings and some timestamps, probably. I'll need it to persist between process exits, though. If I have to write my own config file or something I will, but I figured Winamp might provide something.

Second, are plugins automatically run in a separate thread? I'm planning to do some network I/O and obviously I don't want to freeze up the main window while I wait for responses. I've got a bunch of C++ experience, but all my platform-specific knowledge is Linux. Learning how Windows threads differ from pthreads is probably going to suck, but again I'm hoping that maybe Winamp runs all plugins in their own threads anyway.

Thanks!
Ghantu is offline   Reply With Quote
Old 8th October 2013, 02:41   #2
Ghantu
Junior Member
 
Join Date: Oct 2013
Posts: 3
Well, I figured both of these out on my own, but I figured I'd leave a reply in case anybody gets lead here by a search and has the same questions.

Quote:
Originally Posted by Ghantu View Post
First, is there convenient persistent storage for plugins? I'm not looking for a lot of space, just some config strings and some timestamps, probably. I'll need it to persist between process exits, though. If I have to write my own config file or something I will, but I figured Winamp might provide something.
It turns out working with ini files on Windows is pretty easy. The best thing to do, as far as I can tell, is:

code:
char *dir=(char*)SendMessage(hwnd_winamp,WM_WA_IPC,0,IPC_GETINIDIRECTORY);


Which is from wa_ipc.h in the SDK (search for IPC_GETINIDIRECTORY). That basically gets you to %AppData%\Winamp, but you should probably put your ini file in Plugins, so I did this:

code:

#define INIFILENAME L"\\Plugins\\PLUGIN_NAME_HERE.ini"

// ...

void getInitFileName( wchar_t* filename, size_t numChars )
{
char *dir = (char*)SendMessage( myWinampMediaLibraryPlugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETINIDIRECTORY );
// Convert to a wchar_t*
size_t origsize = strlen( dir ) + 1;
if ( origsize <= numChars )
{
size_t convertedChars = 0;
mbstowcs_s( &convertedChars, filename, origsize, dir, _TRUNCATE );
wcscat_s( filename, numChars, INIFILENAME );
}
}



(Wow, is there a way to avoid the double-spacing inside CODE blocks?)

That converts it to a wchar_t array too, which should be declared in the caller and passed in to this function, like so:

code:

const size_t kPathLen = 512;
wchar_t iniPath[kPathLen];
getInitFileName( iniPath, kPathLen );

// get a string out of the ini file
wchar_t configString[kPathLen]
GetPrivateProfileString( L"sectionName", L"keyNameString", NULL, configString, kPathLen, iniPath );

// get an int out of the ini file
int configInt;
configInt = GetPrivateProfileInt( L"sectionName", L"keyNameInt", 0, iniPath );



Then, if you have to write those values back to the ini file when you exit, you just do this:

code:

WritePrivateProfileString( L"sectionName", L"keyNameString", configString, iniPath );
// There's no WritePrivateProfileInt, so you have to make it a string
wchar_t configIntStr[64];
wsprintf( configIntStr, L"%d", configInt );
WritePrivateProfileString( L"sectionName", L"keyNameInt", configIntStr, iniPath );



Quote:
Originally Posted by Ghantu View Post
Second, are plugins automatically run in a separate thread? I'm planning to do some network I/O and obviously I don't want to freeze up the main window while I wait for responses. I've got a bunch of C++ experience, but all my platform-specific knowledge is Linux. Learning how Windows threads differ from pthreads is probably going to suck, but again I'm hoping that maybe Winamp runs all plugins in their own threads anyway.
Turns out Winamp threads are pretty easy too! I just do this in my init() function:

code:
// global scope
HANDLE threadHandle;

// ...

int init()
{
threadHandle = CreateThread(
NULL, // default security attributes
0, // use default stack size
ThreadFunction, // thread function name
NULL, // argument to thread function
0, // use default creation flags
&threadId); // returns the thread identifier

return 0;
}



And then just do all my work in my thread function. I just use a simple bool for synchronization and set it in quit(), then call

code:
DWORD waitReturn = WaitForSingleObject( threadHandle, 1000 );


That gives the thread a little time to notice that it was told to quit and cleanup. Now's the hard part: figuring out the Winamp XML parser!
Ghantu is offline   Reply With Quote
Old 8th October 2013, 11:46   #3
DrO
 
Join Date: Sep 2003
Posts: 27,873
if you need a unicode version of IPC_GETINIDIRECTORY, there is a native IPC_GETINIDIRECTORYW api available.
DrO is offline   Reply With Quote
Reply
Go Back   Winamp & SHOUTcast Forums > Developer Center > Winamp Development

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump