api_playlists.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #ifndef NULLSOFT_PLAYLIST_API_PLAYLISTS_H
  2. #define NULLSOFT_PLAYLIST_API_PLAYLISTS_H
  3. #include <bfc/dispatch.h>
  4. #include <bfc/platform/guid.h>
  5. #include <bfc/std_mkncc.h>
  6. // manages Winamp's master list of playlists
  7. /* Important note to users of this API:
  8. This API does not actually parse or in any way read the contents of the playlist files themselves.
  9. It only manages the master "list" of playlists, used in e.g. ml_playlists.
  10. --- important ---
  11. This also means that some information retrieved through this API can be inaccurate,
  12. such as playlist item length or total time. These values are provided as a cache,
  13. to speed up display of UI. They are not to be relied on for determining how many items
  14. are actually in the playlist. Don't use this value to allocate memory for data structures,
  15. unless it's just an initial guess and you allow for realloc'ing if the count is higher.
  16. -----------------
  17. It is recommended (but not required) that you call SetInfo to update calculated values,
  18. such as playlist item length, whenever you parse the playlist and have accurate information.
  19. If you need playlist parsing, use api_playlistmanager.
  20. This API is thread-safe, as long as you properly call Lock/Unlock
  21. Methods which don't require external locking are marked with [*]
  22. Note that these methods still lock internally
  23. */
  24. enum
  25. {
  26. API_PLAYLISTS_SUCCESS = 0,
  27. API_PLAYLISTS_FAILURE = 1, // general purpose failure
  28. API_PLAYLISTS_UNKNOWN_INFO_GUID = 2, // bad GUID passed to Set/GetInfo
  29. API_PLAYLISTS_UNABLE_TO_LOAD_PLAYLISTS = 3, // take that variable name, FORTRAN77!
  30. API_PLAYLISTS_INVALID_INDEX = 4, // index you passed was out of range
  31. API_PLAYLISTS_BAD_SIZE = 5, // bad dataLen passed to Set/GetInfo
  32. };
  33. class api_playlists : public Dispatchable
  34. {
  35. protected:
  36. api_playlists() {}
  37. virtual ~api_playlists() {}
  38. public:
  39. // call these to lock the list of playlists so no one changes in the middle of an operation. be careful with this!
  40. // you can use AutoLockT<api_playlists> to help you out
  41. // indices are only valid between these two calls. call GetGUID() if you need session-persistent identifiers
  42. void Lock();
  43. void Unlock();
  44. size_t GetIterator();
  45. /* this value changes each time a modification is made that would invalidate indices previously retrieved.
  46. It does not change when information is changed
  47. Use it to test if your index is out of date.
  48. example:
  49. size_t playlistIterator = playlists->GetIterator();
  50. playlists->GetPosition(myGUID, &index);
  51. // ... do a bunch of stuff
  52. if (playlistIterator != playlists->GetIterator())
  53. playlists->GetPosition(myGUID, &index);
  54. This is meant as a tool to aid implementations that want to cache indices to prevent too many GetPosition() lookups
  55. you don't need this function for casual usage of the API
  56. */
  57. int Sort( size_t sort_type );
  58. void Flush(); // [*] flushes playlists to disk. avoid usage - mainly useful when some program is parsing the playlists.xml file externally
  59. // get information about playlists
  60. size_t GetCount(); // returns number of playlists
  61. const wchar_t *GetFilename( size_t index ); // returns API_PLAYLISTS_SUCCESS or API_PLAYLISTS_FAILURE. only valid until you Unlock()
  62. const wchar_t *GetName( size_t index ); // returns API_PLAYLISTS_SUCCESS or API_PLAYLISTS_FAILURE. only valid until you Unlock()
  63. GUID GetGUID( size_t index ); // retrieves a unique ID which identifies this playlist
  64. 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
  65. 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
  66. // manipulating playlists
  67. // at this time, it is not recommended that you use this API. It is reserved for ml_playlists.
  68. 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
  69. 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
  70. // note: AddPlaylist locks internally, but you need to lock externally if you want to trust the return value
  71. 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
  72. // note: AddCloudPlaylist locks internally, but you need to lock externally if you want to trust the return value
  73. size_t AddPlaylist_NoCallback( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid = INVALID_GUID );
  74. // same as AddPlaylist, but doesn't do a syscallback, use when you want to make a few SetInfo calls,
  75. // when you are done, call WASABI_API_SYSCB->syscb_issueCallback(api_playlists::SYSCALLBACK, api_playlists::PLAYLIST_REMOVED_POST, index, 0); yourself
  76. int SetGUID( size_t index, GUID playlist_guid ); // sets (overrides) a playlist ID. Don't use unless you have some very specific need
  77. int RenamePlaylist( size_t index, const wchar_t *name );
  78. 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.
  79. int SetInfo( size_t index, GUID info, void *data, size_t dataLen ); // returns API_PLAYLISTS_SUCCESS or API_PLAYLISTS_FAILURE
  80. int RemovePlaylist( size_t index ); // removes a particular playlist
  81. int ClearPlaylists(); // [*] clears the entire list of playlists. Use at your own risk :)
  82. /*
  83. callbacks. these are sent through api_syscb.
  84. callbacks are typically done within the api_playlists Lock,
  85. so be careful not to deadlock by waiting on another thread that is also using api_playlists
  86. TODO
  87. probably want move, remove, add
  88. need to think through adding, though. Someone might add a playlist and then SetInfo, so don't want to call syscb too early
  89. */
  90. enum
  91. {
  92. SYSCALLBACK = MK4CC( 'p', 'l', 'a', 'y' ),
  93. PLAYLIST_ADDED = 10, // param1 = index
  94. PLAYLIST_REMOVED_PRE = 20, // param1 = index, called BEFORE it's removed internally, so you can still query for data (Get* function calls)
  95. PLAYLIST_REMOVED_POST = 30, // no parameters, called after it's removed internally
  96. PLAYLIST_RENAMED = 40, // param1 = index
  97. /* These two callbacks are made by you (not api_playlists)
  98. * pass some unique ID as param2 (e.g. some function pointer or pointer to a global variable)
  99. * so that you can identify your own callbacks if you also listen for these events
  100. */
  101. PLAYLIST_SAVED = 50, // param1 = index. You should send this when you save a playlist. Surround with Lock()/Unlock() so that the index is valid
  102. 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
  103. };
  104. enum
  105. {
  106. SORT_TITLE_ASCENDING,
  107. SORT_TITLE_DESCENDING,
  108. SORT_NUMBER_ASCENDING,
  109. SORT_NUMBER_DESCENDING,
  110. };
  111. DISPATCH_CODES
  112. {
  113. API_PLAYLISTS_LOCK = 10,
  114. API_PLAYLISTS_UNLOCK = 20,
  115. API_PLAYLISTS_GETITERATOR = 30,
  116. API_PLAYLISTS_FLUSH = 40,
  117. API_PLAYLISTS_GETCOUNT = 50,
  118. API_PLAYLISTS_GETFILENAME = 60,
  119. API_PLAYLISTS_GETNAME = 70,
  120. API_PLAYLISTS_GETGUID = 80,
  121. API_PLAYLISTS_GETPOSITION = 90,
  122. API_PLAYLISTS_GETINFO = 100,
  123. API_PLAYLISTS_MOVEBEFORE = 110,
  124. API_PLAYLISTS_ADDPLAYLIST = 120,
  125. API_PLAYLISTS_ADDPLAYLISTNOCB = 121,
  126. API_PLAYLISTS_ADDCLOUDPLAYLIST = 122,
  127. API_PLAYLISTS_SETGUID = 130,
  128. API_PLAYLISTS_RENAMEPLAYLIST = 140,
  129. API_PLAYLISTS_MOVEPLAYLIST = 150,
  130. API_PLAYLISTS_SETINFO = 160,
  131. API_PLAYLISTS_REMOVEPLAYLIST = 170,
  132. API_PLAYLISTS_CLEARPLAYLISTS = 180,
  133. API_PLAYLISTS_SORT = 190,
  134. };
  135. };
  136. // Info GUIDS
  137. // {C4FAD6CE-DA38-47b0-AAA9-E966D8E8E7C5}
  138. static const GUID api_playlists_itemCount =
  139. { 0xc4fad6ce, 0xda38, 0x47b0, { 0xaa, 0xa9, 0xe9, 0x66, 0xd8, 0xe8, 0xe7, 0xc5 } };
  140. // {D4E0E000-A3F5-4f18-ADA5-F2BA40689593}
  141. static const GUID api_playlists_totalTime =
  142. { 0xd4e0e000, 0xa3f5, 0x4f18, { 0xad, 0xa5, 0xf2, 0xba, 0x40, 0x68, 0x95, 0x93 } };
  143. // {F6E1AB19-6931-4cc9-BCBA-4B40DE2A959F}
  144. static const GUID api_playlists_iTunesID =
  145. { 0xf6e1ab19, 0x6931, 0x4cc9, { 0xbc, 0xba, 0x4b, 0x40, 0xde, 0x2a, 0x95, 0x9f } };
  146. // {B83AD244-7CD3-4a24-B2C5-41F42CA37F14}
  147. static const GUID api_playlists_cloud =
  148. { 0xb83ad244, 0x7cd3, 0x4a24, { 0xb2, 0xc5, 0x41, 0xf4, 0x2c, 0xa3, 0x7f, 0x14 } };
  149. inline void api_playlists::Lock()
  150. {
  151. _voidcall( API_PLAYLISTS_LOCK );
  152. }
  153. inline void api_playlists::Unlock()
  154. {
  155. _voidcall( API_PLAYLISTS_UNLOCK );
  156. }
  157. inline size_t api_playlists::GetIterator()
  158. {
  159. return _call( API_PLAYLISTS_GETITERATOR, 0 );
  160. }
  161. inline void api_playlists::Flush()
  162. {
  163. _voidcall( API_PLAYLISTS_FLUSH );
  164. }
  165. inline int api_playlists::Sort( size_t sort_type )
  166. {
  167. return _call( API_PLAYLISTS_SORT, 0, sort_type );
  168. }
  169. inline size_t api_playlists::GetCount()
  170. {
  171. return _call( API_PLAYLISTS_GETCOUNT, 0 );
  172. }
  173. inline const wchar_t *api_playlists::GetFilename( size_t index )
  174. {
  175. return _call( API_PLAYLISTS_GETFILENAME, (const wchar_t *)0, index );
  176. }
  177. inline const wchar_t *api_playlists::GetName( size_t index )
  178. {
  179. return _call( API_PLAYLISTS_GETNAME, (const wchar_t *)0, index );
  180. }
  181. inline GUID api_playlists::GetGUID( size_t index )
  182. {
  183. return _call( API_PLAYLISTS_GETGUID, INVALID_GUID, index );
  184. }
  185. inline int api_playlists::GetPosition( GUID playlist_guid, size_t *index )
  186. {
  187. return _call( API_PLAYLISTS_GETPOSITION, API_PLAYLISTS_FAILURE, playlist_guid, index );
  188. }
  189. inline int api_playlists::GetInfo( size_t index, GUID info, void *data, size_t dataLen )
  190. {
  191. return _call( API_PLAYLISTS_GETINFO, API_PLAYLISTS_FAILURE, index, info, data, dataLen );
  192. }
  193. inline int api_playlists::MoveBefore( size_t index1, size_t index2 )
  194. {
  195. return _call( API_PLAYLISTS_MOVEBEFORE, API_PLAYLISTS_FAILURE, index1, index2 );
  196. }
  197. inline size_t api_playlists::AddPlaylist( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid )
  198. {
  199. return _call( API_PLAYLISTS_ADDPLAYLIST, (size_t)-1, filename, playlistName, playlist_guid );
  200. }
  201. inline size_t api_playlists::AddPlaylist_NoCallback( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid )
  202. {
  203. return _call( API_PLAYLISTS_ADDPLAYLISTNOCB, (size_t)-1, filename, playlistName, playlist_guid );
  204. }
  205. inline size_t api_playlists::AddCloudPlaylist( const wchar_t *filename, const wchar_t *playlistName, GUID playlist_guid )
  206. {
  207. return _call( API_PLAYLISTS_ADDCLOUDPLAYLIST, (size_t)-1, filename, playlistName, playlist_guid );
  208. }
  209. inline int api_playlists::SetGUID( size_t index, GUID playlist_guid )
  210. {
  211. return _call( API_PLAYLISTS_SETGUID, API_PLAYLISTS_FAILURE, index, playlist_guid );
  212. }
  213. inline int api_playlists::RenamePlaylist( size_t index, const wchar_t *name )
  214. {
  215. return _call( API_PLAYLISTS_RENAMEPLAYLIST, API_PLAYLISTS_FAILURE, index, name );
  216. }
  217. inline int api_playlists::MovePlaylist( size_t index, const wchar_t *filename )
  218. {
  219. return _call( API_PLAYLISTS_MOVEPLAYLIST, API_PLAYLISTS_FAILURE, index, filename );
  220. }
  221. inline int api_playlists::SetInfo( size_t index, GUID info, void *data, size_t dataLen )
  222. {
  223. return _call( API_PLAYLISTS_SETINFO, API_PLAYLISTS_FAILURE, index, info, data, dataLen );
  224. }
  225. inline int api_playlists::RemovePlaylist( size_t index )
  226. {
  227. return _call( API_PLAYLISTS_REMOVEPLAYLIST, API_PLAYLISTS_FAILURE, index );
  228. }
  229. inline int api_playlists::ClearPlaylists()
  230. {
  231. return _call( API_PLAYLISTS_CLEARPLAYLISTS, API_PLAYLISTS_FAILURE );
  232. }
  233. // {2DC3C390-D9B8-4a49-B230-EF240ADDDCDB}
  234. static const GUID api_playlistsGUID =
  235. { 0x2dc3c390, 0xd9b8, 0x4a49, { 0xb2, 0x30, 0xef, 0x24, 0xa, 0xdd, 0xdc, 0xdb } };
  236. #endif