summaryrefslogtreecommitdiffstats
path: root/Src/playlist/api_playlists.h
blob: 6e205b0fb54512de5202b7146e9ea4b05f8f03cd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
#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