winamp/Src/playlist/api_playlists.h
2024-09-24 14:54:57 +02:00

290 lines
12 KiB
C++

#ifndef NULLSOFT_PLAYLIST_API_PLAYLISTS_H
#define NULLSOFT_PLAYLIST_API_PLAYLISTS_H
#include <bfc/dispatch.h>
#include <bfc/platform/guid.h>
#include <bfc/std_mkncc.h>
// manages Winamp's master list of playlists
/* Important note to users of this API:
This API does not actually parse or in any way read the contents of the playlist files themselves.
It only manages the master "list" of playlists, used in e.g. ml_playlists.
--- important ---
This also means that some information retrieved through this API can be inaccurate,
such as playlist item length or total time. These values are provided as a cache,
to speed up display of UI. They are not to be relied on for determining how many items
are actually in the playlist. Don't use this value to allocate memory for data structures,
unless it's just an initial guess and you allow for realloc'ing if the count is higher.
-----------------
It is recommended (but not required) that you call SetInfo to update calculated values,
such as playlist item length, whenever you parse the playlist and have accurate information.
If you need playlist parsing, use api_playlistmanager.
This API is thread-safe, as long as you properly call Lock/Unlock
Methods which don't require external locking are marked with [*]
Note that these methods still lock internally
*/
enum
{
API_PLAYLISTS_SUCCESS = 0,
API_PLAYLISTS_FAILURE = 1, // general purpose failure
API_PLAYLISTS_UNKNOWN_INFO_GUID = 2, // bad GUID passed to Set/GetInfo
API_PLAYLISTS_UNABLE_TO_LOAD_PLAYLISTS = 3, // take that variable name, FORTRAN77!
API_PLAYLISTS_INVALID_INDEX = 4, // index you passed was out of range
API_PLAYLISTS_BAD_SIZE = 5, // bad dataLen passed to Set/GetInfo
};
class api_playlists : public Dispatchable
{
protected:
api_playlists() {}
virtual ~api_playlists() {}
public:
// call these to lock the list of playlists so no one changes in the middle of an operation. be careful with this!
// you can use AutoLockT<api_playlists> to help you out
// indices are only valid between these two calls. call GetGUID() if you need session-persistent identifiers
void Lock();
void Unlock();
size_t GetIterator();
/* this value changes each time a modification is made that would invalidate indices previously retrieved.
It does not change when information is changed
Use it to test if your index is out of date.
example:
size_t playlistIterator = playlists->GetIterator();
playlists->GetPosition(myGUID, &index);
// ... do a bunch of stuff
if (playlistIterator != playlists->GetIterator())
playlists->GetPosition(myGUID, &index);
This is meant as a tool to aid implementations that want to cache indices to prevent too many GetPosition() lookups
you don't need this function for casual usage of the API
*/
int Sort( size_t sort_type );
void Flush(); // [*] flushes playlists to disk. avoid usage - mainly useful when some program is parsing the playlists.xml file externally
// get information about playlists
size_t GetCount(); // returns number of playlists
const wchar_t *GetFilename( size_t index ); // returns API_PLAYLISTS_SUCCESS or API_PLAYLISTS_FAILURE. only valid until you Unlock()
const wchar_t *GetName( size_t index ); // returns API_PLAYLISTS_SUCCESS or API_PLAYLISTS_FAILURE. only valid until you Unlock()
GUID GetGUID( size_t index ); // retrieves a unique ID which identifies this playlist
int GetPosition( GUID playlist_guid, size_t *index ); // retrieves the index where a particular playlist ID lives. returns API_PLAYLISTS_SUCCESS or API_PLAYLISTS_FAILURE
int GetInfo( size_t index, GUID info, void *data, size_t dataLen ); // This is for getting "extra" data, see list of GUIDs below. returns API_PLAYLISTS_SUCCESS or API_PLAYLISTS_FAILURE
// manipulating playlists
// at this time, it is not recommended that you use this API. It is reserved for ml_playlists.
int MoveBefore( size_t index1, size_t index2 ); // moves playlist at position index1 to before index2. setting index2 to anything larger than GetCount() moves to end
size_t AddPlaylist( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid = INVALID_GUID ); // [*] adds a new playlist, returns new index. Generates a GUID if you don't pass third parameter. returns (size_t)-1 on error and (size_t)-2 if already exists
// note: AddPlaylist locks internally, but you need to lock externally if you want to trust the return value
size_t AddCloudPlaylist( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid = INVALID_GUID ); // [*] adds a new playlist, returns new index. Generates a GUID if you don't pass third parameter. returns (size_t)-1 on error and (size_t)-2 if already exists
// note: AddCloudPlaylist locks internally, but you need to lock externally if you want to trust the return value
size_t AddPlaylist_NoCallback( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid = INVALID_GUID );
// same as AddPlaylist, but doesn't do a syscallback, use when you want to make a few SetInfo calls,
// when you are done, call WASABI_API_SYSCB->syscb_issueCallback(api_playlists::SYSCALLBACK, api_playlists::PLAYLIST_REMOVED_POST, index, 0); yourself
int SetGUID( size_t index, GUID playlist_guid ); // sets (overrides) a playlist ID. Don't use unless you have some very specific need
int RenamePlaylist( size_t index, const wchar_t *name );
int MovePlaylist( size_t index, const wchar_t *filename ); // sets a new filename. NOTE: IT'S UP TO YOU TO PHYSICALLY MOVE/RENAME/CREATE THE NEW FILENAME.
int SetInfo( size_t index, GUID info, void *data, size_t dataLen ); // returns API_PLAYLISTS_SUCCESS or API_PLAYLISTS_FAILURE
int RemovePlaylist( size_t index ); // removes a particular playlist
int ClearPlaylists(); // [*] clears the entire list of playlists. Use at your own risk :)
/*
callbacks. these are sent through api_syscb.
callbacks are typically done within the api_playlists Lock,
so be careful not to deadlock by waiting on another thread that is also using api_playlists
TODO
probably want move, remove, add
need to think through adding, though. Someone might add a playlist and then SetInfo, so don't want to call syscb too early
*/
enum
{
SYSCALLBACK = MK4CC( 'p', 'l', 'a', 'y' ),
PLAYLIST_ADDED = 10, // param1 = index
PLAYLIST_REMOVED_PRE = 20, // param1 = index, called BEFORE it's removed internally, so you can still query for data (Get* function calls)
PLAYLIST_REMOVED_POST = 30, // no parameters, called after it's removed internally
PLAYLIST_RENAMED = 40, // param1 = index
/* These two callbacks are made by you (not api_playlists)
* pass some unique ID as param2 (e.g. some function pointer or pointer to a global variable)
* so that you can identify your own callbacks if you also listen for these events
*/
PLAYLIST_SAVED = 50, // param1 = index. You should send this when you save a playlist. Surround with Lock()/Unlock() so that the index is valid
PLAYLIST_FLUSH_REQUEST = 60, // param1 = index. Call before you load a playlist to request anyone who might be currently modifying the same playlist to save
};
enum
{
SORT_TITLE_ASCENDING,
SORT_TITLE_DESCENDING,
SORT_NUMBER_ASCENDING,
SORT_NUMBER_DESCENDING,
};
DISPATCH_CODES
{
API_PLAYLISTS_LOCK = 10,
API_PLAYLISTS_UNLOCK = 20,
API_PLAYLISTS_GETITERATOR = 30,
API_PLAYLISTS_FLUSH = 40,
API_PLAYLISTS_GETCOUNT = 50,
API_PLAYLISTS_GETFILENAME = 60,
API_PLAYLISTS_GETNAME = 70,
API_PLAYLISTS_GETGUID = 80,
API_PLAYLISTS_GETPOSITION = 90,
API_PLAYLISTS_GETINFO = 100,
API_PLAYLISTS_MOVEBEFORE = 110,
API_PLAYLISTS_ADDPLAYLIST = 120,
API_PLAYLISTS_ADDPLAYLISTNOCB = 121,
API_PLAYLISTS_ADDCLOUDPLAYLIST = 122,
API_PLAYLISTS_SETGUID = 130,
API_PLAYLISTS_RENAMEPLAYLIST = 140,
API_PLAYLISTS_MOVEPLAYLIST = 150,
API_PLAYLISTS_SETINFO = 160,
API_PLAYLISTS_REMOVEPLAYLIST = 170,
API_PLAYLISTS_CLEARPLAYLISTS = 180,
API_PLAYLISTS_SORT = 190,
};
};
// Info GUIDS
// {C4FAD6CE-DA38-47b0-AAA9-E966D8E8E7C5}
static const GUID api_playlists_itemCount =
{ 0xc4fad6ce, 0xda38, 0x47b0, { 0xaa, 0xa9, 0xe9, 0x66, 0xd8, 0xe8, 0xe7, 0xc5 } };
// {D4E0E000-A3F5-4f18-ADA5-F2BA40689593}
static const GUID api_playlists_totalTime =
{ 0xd4e0e000, 0xa3f5, 0x4f18, { 0xad, 0xa5, 0xf2, 0xba, 0x40, 0x68, 0x95, 0x93 } };
// {F6E1AB19-6931-4cc9-BCBA-4B40DE2A959F}
static const GUID api_playlists_iTunesID =
{ 0xf6e1ab19, 0x6931, 0x4cc9, { 0xbc, 0xba, 0x4b, 0x40, 0xde, 0x2a, 0x95, 0x9f } };
// {B83AD244-7CD3-4a24-B2C5-41F42CA37F14}
static const GUID api_playlists_cloud =
{ 0xb83ad244, 0x7cd3, 0x4a24, { 0xb2, 0xc5, 0x41, 0xf4, 0x2c, 0xa3, 0x7f, 0x14 } };
inline void api_playlists::Lock()
{
_voidcall( API_PLAYLISTS_LOCK );
}
inline void api_playlists::Unlock()
{
_voidcall( API_PLAYLISTS_UNLOCK );
}
inline size_t api_playlists::GetIterator()
{
return _call( API_PLAYLISTS_GETITERATOR, 0 );
}
inline void api_playlists::Flush()
{
_voidcall( API_PLAYLISTS_FLUSH );
}
inline int api_playlists::Sort( size_t sort_type )
{
return _call( API_PLAYLISTS_SORT, 0, sort_type );
}
inline size_t api_playlists::GetCount()
{
return _call( API_PLAYLISTS_GETCOUNT, 0 );
}
inline const wchar_t *api_playlists::GetFilename( size_t index )
{
return _call( API_PLAYLISTS_GETFILENAME, (const wchar_t *)0, index );
}
inline const wchar_t *api_playlists::GetName( size_t index )
{
return _call( API_PLAYLISTS_GETNAME, (const wchar_t *)0, index );
}
inline GUID api_playlists::GetGUID( size_t index )
{
return _call( API_PLAYLISTS_GETGUID, INVALID_GUID, index );
}
inline int api_playlists::GetPosition( GUID playlist_guid, size_t *index )
{
return _call( API_PLAYLISTS_GETPOSITION, API_PLAYLISTS_FAILURE, playlist_guid, index );
}
inline int api_playlists::GetInfo( size_t index, GUID info, void *data, size_t dataLen )
{
return _call( API_PLAYLISTS_GETINFO, API_PLAYLISTS_FAILURE, index, info, data, dataLen );
}
inline int api_playlists::MoveBefore( size_t index1, size_t index2 )
{
return _call( API_PLAYLISTS_MOVEBEFORE, API_PLAYLISTS_FAILURE, index1, index2 );
}
inline size_t api_playlists::AddPlaylist( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid )
{
return _call( API_PLAYLISTS_ADDPLAYLIST, (size_t)-1, filename, playlistName, playlist_guid );
}
inline size_t api_playlists::AddPlaylist_NoCallback( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid )
{
return _call( API_PLAYLISTS_ADDPLAYLISTNOCB, (size_t)-1, filename, playlistName, playlist_guid );
}
inline size_t api_playlists::AddCloudPlaylist( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid )
{
return _call( API_PLAYLISTS_ADDCLOUDPLAYLIST, (size_t)-1, filename, playlistName, playlist_guid );
}
inline int api_playlists::SetGUID( size_t index, GUID playlist_guid )
{
return _call( API_PLAYLISTS_SETGUID, API_PLAYLISTS_FAILURE, index, playlist_guid );
}
inline int api_playlists::RenamePlaylist( size_t index, const wchar_t *name )
{
return _call( API_PLAYLISTS_RENAMEPLAYLIST, API_PLAYLISTS_FAILURE, index, name );
}
inline int api_playlists::MovePlaylist( size_t index, const wchar_t *filename )
{
return _call( API_PLAYLISTS_MOVEPLAYLIST, API_PLAYLISTS_FAILURE, index, filename );
}
inline int api_playlists::SetInfo( size_t index, GUID info, void *data, size_t dataLen )
{
return _call( API_PLAYLISTS_SETINFO, API_PLAYLISTS_FAILURE, index, info, data, dataLen );
}
inline int api_playlists::RemovePlaylist( size_t index )
{
return _call( API_PLAYLISTS_REMOVEPLAYLIST, API_PLAYLISTS_FAILURE, index );
}
inline int api_playlists::ClearPlaylists()
{
return _call( API_PLAYLISTS_CLEARPLAYLISTS, API_PLAYLISTS_FAILURE );
}
// {2DC3C390-D9B8-4a49-B230-EF240ADDDCDB}
static const GUID api_playlistsGUID =
{ 0x2dc3c390, 0xd9b8, 0x4a49, { 0xb2, 0x30, 0xef, 0x24, 0xa, 0xdd, 0xdc, 0xdb } };
#endif