SendTo.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. #include <strsafe.h>
  2. #include "main.h"
  3. #include "api__ml_playlists.h"
  4. #include "Playlist.h"
  5. #include "PlaylistView.h"
  6. #include "resource.h"
  7. #include "../nu/AutoWideFn.h"
  8. #include <vector>
  9. /* TODO:
  10. Somehow replace index values in send-to with GUID's. Possibly by making a vector of GUIDs (like view_playlists).
  11. Since index values could (in theory) change in a background thread while send-to interaction is going on.
  12. */
  13. extern Playlist currentPlaylist;
  14. using namespace Nullsoft::Utility;
  15. static std::vector<GUID> sendto_playlistGUIDs;
  16. int playlists_CloudAvailable()
  17. {
  18. if (IPC_GET_CLOUD_HINST == -1) IPC_GET_CLOUD_HINST = (INT)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"WinampCloud", IPC_REGISTER_WINAMP_IPCMESSAGE);
  19. if (IPC_GET_CLOUD_ACTIVE == -1) IPC_GET_CLOUD_ACTIVE = (INT)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"WinampCloudActive", IPC_REGISTER_WINAMP_IPCMESSAGE);
  20. if (!cloud_hinst) cloud_hinst = (HINSTANCE)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GET_CLOUD_HINST);
  21. return (cloud_avail = /*0/*/!(!cloud_hinst || cloud_hinst == (HINSTANCE)1 || !SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GET_CLOUD_ACTIVE))/**/);
  22. }
  23. int playlists_CloudInstalled()
  24. {
  25. if (IPC_GET_CLOUD_HINST == -1) IPC_GET_CLOUD_HINST = (INT)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&"WinampCloud", IPC_REGISTER_WINAMP_IPCMESSAGE);
  26. if (!cloud_hinst) cloud_hinst = (HINSTANCE)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GET_CLOUD_HINST);
  27. return (!(!cloud_hinst || cloud_hinst == (HINSTANCE)1));
  28. }
  29. int playlists_BuildSendTo(int sourceType, INT_PTR context)
  30. {
  31. if (sourceType == ML_TYPE_ITEMRECORDLISTW || sourceType == ML_TYPE_ITEMRECORDLIST ||
  32. sourceType == ML_TYPE_FILENAMES || sourceType == ML_TYPE_STREAMNAMES ||
  33. sourceType == ML_TYPE_FILENAMESW || sourceType == ML_TYPE_STREAMNAMESW ||
  34. sourceType == ML_TYPE_CDTRACKS)
  35. {
  36. if (g_config->ReadInt(L"pl_send_to", DEFAULT_PL_SEND_TO))
  37. {
  38. mediaLibrary.BranchSendTo(context);
  39. mediaLibrary.AddToSendTo(WASABI_API_LNGSTRINGW(IDS_SENDTO_NEW_PLAYLIST), context, playlistsTreeId);
  40. AutoLockT<api_playlists> lock (AGAVE_API_PLAYLISTS);
  41. sendto_playlistGUIDs.clear();
  42. size_t count = AGAVE_API_PLAYLISTS->GetCount();
  43. for (size_t i = 0;i != count;i++)
  44. {
  45. PlaylistInfo info(i);
  46. if (info.Valid())
  47. {
  48. sendto_playlistGUIDs.push_back(info.playlist_guid);
  49. if (sendToIgnoreID != info.treeId)
  50. {
  51. mediaLibrary.AddToBranchSendTo(info.GetName(), context, reinterpret_cast<INT_PTR>(pluginMessageProc) + i);
  52. }
  53. }
  54. }
  55. mediaLibrary.EndBranchSendTo(WASABI_API_LNGSTRINGW(IDS_SENDTO_ML_PLAYLISTS), context);
  56. }
  57. else
  58. {
  59. mediaLibrary.AddToSendTo(WASABI_API_LNGSTRINGW(IDS_SENDTO_PLAYLIST), context, playlistsTreeId);
  60. }
  61. }
  62. return 0;
  63. }
  64. static void NewPlaylist( Playlist &newPlaylist, const wchar_t *playlistTitle, int makeTree, const wchar_t *newFilename = 0 )
  65. {
  66. if ( playlistTitle && *playlistTitle )
  67. {
  68. size_t numItems = newPlaylist.GetNumItems();
  69. wchar_t filename[ 1024 + 256 ] = { 0 };
  70. if ( newFilename )
  71. {
  72. if ( PathIsFileSpecW( newFilename ) )
  73. PathCombineW( filename, g_path, newFilename );
  74. else
  75. lstrcpynW( filename, newFilename, MAX_PATH );
  76. }
  77. else
  78. PathCombineW( filename, g_path, createPlayListDBFileName( filename ) );
  79. AGAVE_API_PLAYLISTMANAGER->Save( filename, &newPlaylist );
  80. AddPlaylist( true, playlistTitle, filename, ( LOWORD( makeTree ) != 0 ), HIWORD( makeTree ), numItems, newPlaylist.lengthInMS );
  81. }
  82. else
  83. {
  84. AutoLockT<api_playlists> lock( AGAVE_API_PLAYLISTS );
  85. size_t a = AGAVE_API_PLAYLISTS->GetCount();
  86. playlists_Add( plugin.hwndLibraryParent, false );
  87. if ( AGAVE_API_PLAYLISTS->GetCount() == a + 1 )
  88. {
  89. PlaylistInfo info( a );
  90. if ( info.Valid() )
  91. {
  92. info.SetLength( (int)( newPlaylist.lengthInMS > 0 ? newPlaylist.lengthInMS / 1000 : 0 ) );
  93. info.SetSize( newPlaylist.GetNumItems() );
  94. info.SetCloud( HIWORD( makeTree ) );
  95. wchar_t fn[ MAX_PATH ] = { 0 };
  96. if ( PathIsFileSpecW( info.GetFilename() ) )
  97. PathCombineW( fn, g_path, info.GetFilename() );
  98. else
  99. lstrcpynW( fn, info.GetFilename(), MAX_PATH );
  100. for ( pl_entry *l_entry : newPlaylist.entries )
  101. {
  102. for ( pl_entry *l_current_entry : currentPlaylist.entries )
  103. {
  104. if ( wcscmp( l_entry->filename, l_current_entry->filename ) == 0 )
  105. {
  106. //SetTitle releases previously allocated string, no need to free previous one
  107. l_entry->SetTitle(l_current_entry->filetitle);
  108. if ( !l_current_entry->_extended_infos.empty() )
  109. {
  110. for ( auto l_current_extended_info : l_current_entry->_extended_infos )
  111. l_entry->_extended_infos.emplace( _wcsdup( l_current_extended_info.first.c_str() ), _wcsdup( l_current_extended_info.second.c_str() ) );
  112. }
  113. break;
  114. }
  115. }
  116. }
  117. AGAVE_API_PLAYLISTMANAGER->Save( fn, &newPlaylist );
  118. // delay the added notification being sent so for the cloud
  119. // we can have the complete playlist available to work with
  120. AGAVE_API_PLAYLISTS->Flush();
  121. WASABI_API_SYSCB->syscb_issueCallback( api_playlists::SYSCALLBACK, api_playlists::PLAYLIST_ADDED, a/* + 1*/, 0 );
  122. UpdateTree( info, info.treeId );
  123. }
  124. }
  125. }
  126. RefreshPlaylistsList();
  127. }
  128. void AddPlaylistFromFilenames(const char *filenames, const wchar_t *playlistTitle, int makeTree, const wchar_t *filename)
  129. {
  130. Playlist newPlaylist;
  131. while (filenames && *filenames)
  132. {
  133. AutoWide wideFn(filenames);
  134. if (AGAVE_API_PLAYLISTMANAGER->Load(wideFn, &newPlaylist) != PLAYLISTMANAGER_SUCCESS) // try to load it as a playlist first
  135. {
  136. wchar_t title[FILETITLE_SIZE] = {0};
  137. int length = 0;
  138. mediaLibrary.GetFileInfo(wideFn, title, FILETITLE_SIZE, &length);
  139. newPlaylist.AppendWithInfo(wideFn, title, length*1000); // otherwise just add it to the playlist directly
  140. }
  141. filenames += strlen(filenames) + 1;
  142. }
  143. NewPlaylist(newPlaylist, playlistTitle, makeTree, filename);
  144. }
  145. void AddPlaylistFromFilenamesW(const wchar_t *filenames, const wchar_t *playlistTitle, int makeTree, const wchar_t *filename)
  146. {
  147. Playlist newPlaylist;
  148. while (filenames && *filenames)
  149. {
  150. if (AGAVE_API_PLAYLISTMANAGER->Load(filenames, &newPlaylist) != PLAYLISTMANAGER_SUCCESS) // try to load it as a playlist first
  151. {
  152. wchar_t title[FILETITLE_SIZE] = {0};
  153. int length = 0;
  154. mediaLibrary.GetFileInfo(filenames, title, FILETITLE_SIZE, &length);
  155. newPlaylist.AppendWithInfo(filenames, title, (length > 0 ? length*1000 : 0)); // otherwise just add it to the playlist directly
  156. }
  157. filenames += wcslen(filenames) + 1;
  158. }
  159. NewPlaylist(newPlaylist, playlistTitle, makeTree, filename);
  160. }
  161. static wchar_t *itemrecordTagFunc(wchar_t *tag, void * p) //return 0 if not found
  162. {
  163. itemRecord *t = (itemRecord *)p;
  164. char buf[128] = {0};
  165. char *value = NULL;
  166. if (!_wcsicmp(tag, L"artist")) value = t->artist;
  167. else if (!_wcsicmp(tag, L"album")) value = t->album;
  168. else if (!_wcsicmp(tag, L"filename")) value = t->filename;
  169. else if (!_wcsicmp(tag, L"title")) value = t->title;
  170. else if (!_wcsicmp(tag, L"ext")) value = t->ext;
  171. else if (!_wcsicmp(tag, L"year"))
  172. {
  173. if (t->year > 0)
  174. {
  175. StringCchPrintfA(buf, 128, "%04d", t->year);
  176. value = buf;
  177. }
  178. }
  179. else if (!_wcsicmp(tag, L"genre")) value = t->genre;
  180. else if (!_wcsicmp(tag, L"comment")) value = t->comment;
  181. else if (!_wcsicmp(tag, L"tracknumber") || !_wcsicmp(tag, L"track"))
  182. {
  183. if (t->track > 0)
  184. {
  185. StringCchPrintfA(buf, 128, "%02d", t->track);
  186. value = buf;
  187. }
  188. }
  189. else if (!_wcsicmp(tag, L"rating")) value = getRecordExtendedItem(t, "RATING");
  190. else if (!_wcsicmp(tag, L"playcount")) value = getRecordExtendedItem(t, "PLAYCOUNT");
  191. else if (!_wcsicmp(tag, L"bitrate")) value = getRecordExtendedItem(t, "BITRATE");
  192. else
  193. return 0;
  194. if (!value) return reinterpret_cast<wchar_t *>(-1);
  195. else return AutoWideDup(value);
  196. }
  197. static wchar_t *itemrecordWTagFunc(wchar_t *tag, void * p) //return 0 if not found
  198. {
  199. itemRecordW *t = (itemRecordW *)p;
  200. wchar_t buf[128] = {0};
  201. wchar_t *value = NULL;
  202. // TODO: more fields
  203. if (!_wcsicmp(tag, L"artist")) value = t->artist;
  204. else if (!_wcsicmp(tag, L"album")) value = t->album;
  205. else if (!_wcsicmp(tag, L"filename")) value = t->filename;
  206. else if (!_wcsicmp(tag, L"title")) value = t->title;
  207. else if (!_wcsicmp(tag, L"year"))
  208. {
  209. if (t->year > 0)
  210. {
  211. StringCchPrintfW(buf, 128, L"%04d", t->year);
  212. value = buf;
  213. }
  214. }
  215. else if (!_wcsicmp(tag, L"genre")) value = t->genre;
  216. else if (!_wcsicmp(tag, L"comment")) value = t->comment;
  217. else if (!_wcsicmp(tag, L"tracknumber") || !_wcsicmp(tag, L"track"))
  218. {
  219. if (t->track > 0)
  220. {
  221. StringCchPrintfW(buf, 128, L"%02d", t->track);
  222. value = buf;
  223. }
  224. }
  225. else if (!_wcsicmp(tag, L"rating"))
  226. {
  227. if (t->rating > 0)
  228. {
  229. StringCchPrintfW(buf, 128, L"%d", t->rating);
  230. value = buf;
  231. }
  232. }
  233. else if (!_wcsicmp(tag, L"playcount")) value = t->comment;
  234. else if (!_wcsicmp(tag, L"bitrate"))
  235. {
  236. if (t->bitrate > 0)
  237. {
  238. StringCchPrintfW(buf, 128, L"%d", t->bitrate);
  239. value = buf;
  240. }
  241. }
  242. else
  243. return 0;
  244. if (!value) return reinterpret_cast<wchar_t *>(-1);
  245. else return _wcsdup(value);
  246. }
  247. static void fieldTagFuncFree(char * tag, void * p)
  248. {
  249. free(tag);
  250. }
  251. static void BuildTitle(itemRecord *record, wchar_t *title, int lenCch)
  252. {
  253. AutoWideFn wfn(record->filename);
  254. waFormatTitleExtended fmt;
  255. fmt.filename = wfn;
  256. fmt.useExtendedInfo = 1;
  257. fmt.out = title;
  258. fmt.out_len = lenCch;
  259. fmt.p = record;
  260. fmt.spec = 0;
  261. *(void **)&fmt.TAGFUNC = itemrecordTagFunc;
  262. *(void **)&fmt.TAGFREEFUNC = fieldTagFuncFree;
  263. *title = 0;
  264. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&fmt, IPC_FORMAT_TITLE_EXTENDED);
  265. }
  266. static void BuildTitleW(itemRecordW *record, wchar_t *title, int lenCch)
  267. {
  268. waFormatTitleExtended fmt;
  269. fmt.filename = record->filename;
  270. fmt.useExtendedInfo = 1;
  271. fmt.out = title;
  272. fmt.out_len = lenCch;
  273. fmt.p = record;
  274. fmt.spec = 0;
  275. *(void **)&fmt.TAGFUNC = itemrecordWTagFunc;
  276. *(void **)&fmt.TAGFREEFUNC = fieldTagFuncFree;
  277. *title = 0;
  278. SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&fmt, IPC_FORMAT_TITLE_EXTENDED);
  279. }
  280. void AddPlaylistFromItemRecordList(itemRecordList *obj, const wchar_t *playlistTitle, int makeTree, const wchar_t *filename)
  281. {
  282. Playlist newPlaylist;
  283. wchar_t title[FILETITLE_SIZE] = {0};
  284. for (int x = 0; x < obj->Size; x ++)
  285. {
  286. BuildTitle(&obj->Items[x], title, FILETITLE_SIZE);
  287. newPlaylist.AppendWithInfo(AutoWide(obj->Items[x].filename), title, obj->Items[x].length*1000);
  288. }
  289. NewPlaylist(newPlaylist, playlistTitle, makeTree, filename);
  290. }
  291. void AddPlaylistFromItemRecordListW(itemRecordListW *obj, const wchar_t *playlistTitle, int makeTree, const wchar_t *filename)
  292. {
  293. Playlist newPlaylist;
  294. wchar_t title[FILETITLE_SIZE] = {0};
  295. for (int x = 0; x < obj->Size; x ++)
  296. {
  297. BuildTitleW(&obj->Items[x], title, FILETITLE_SIZE);
  298. newPlaylist.AppendWithInfo(obj->Items[x].filename, title, obj->Items[x].length*1000);
  299. }
  300. NewPlaylist(newPlaylist, playlistTitle, makeTree, filename);
  301. }
  302. static void AddToPlaylist(GUID playlist_guid, int sourceType, INT_PTR data)
  303. {
  304. AutoLockT<api_playlists> lock (AGAVE_API_PLAYLISTS);
  305. playlist_Save(plugin.hwndWinampParent);
  306. PlaylistInfo p(playlist_guid);
  307. if (p.Valid())
  308. {
  309. Playlist playlist;
  310. AGAVE_API_PLAYLISTMANAGER->Load(p.GetFilename(), &playlist);
  311. if (sourceType == ML_TYPE_FILENAMES || sourceType == ML_TYPE_STREAMNAMES)
  312. {
  313. const char *ptr = (const char*)data;
  314. while (ptr && *ptr)
  315. {
  316. AutoWide wideFn(ptr);
  317. // try to load in playlist manager first
  318. Playlist sentPlaylist;
  319. if (sourceType == ML_TYPE_FILENAMES
  320. && AGAVE_API_PLAYLISTMANAGER->Load(wideFn, &sentPlaylist) == PLAYLISTMANAGER_SUCCESS)
  321. {
  322. playlist.AppendPlaylist(sentPlaylist);
  323. }
  324. else
  325. {
  326. wchar_t title[FILETITLE_SIZE] = {0};
  327. int length = -1;
  328. mediaLibrary.GetFileInfo(wideFn, title, FILETITLE_SIZE, &length);
  329. playlist.AppendWithInfo(wideFn, title, length*1000);
  330. }
  331. ptr += strlen(ptr) + 1;
  332. }
  333. }
  334. else if (sourceType == ML_TYPE_FILENAMESW || sourceType == ML_TYPE_STREAMNAMESW)
  335. {
  336. const wchar_t *ptr = (const wchar_t*)data;
  337. while (ptr && *ptr)
  338. {
  339. // try to load in playlist manager first
  340. Playlist sentPlaylist;
  341. if (sourceType == ML_TYPE_FILENAMES
  342. && AGAVE_API_PLAYLISTMANAGER->Load(ptr, &sentPlaylist) == PLAYLISTMANAGER_SUCCESS)
  343. {
  344. playlist.AppendPlaylist(sentPlaylist);
  345. }
  346. else
  347. {
  348. wchar_t title[FILETITLE_SIZE] = {0};
  349. int length = -1;
  350. mediaLibrary.GetFileInfo(ptr, title, FILETITLE_SIZE, &length);
  351. std::map<std::wstring, std::wstring> l_extended_infos;
  352. if ( PathIsURLW( title ) )
  353. {
  354. wchar_t *end = 0;
  355. for ( pl_entry *l_current_entry : currentPlaylist.entries )
  356. {
  357. if ( wcscmp( title, l_current_entry->filename ) == 0 )
  358. {
  359. StringCchCopyExW( title, FILETITLE_SIZE, l_current_entry->filetitle, &end, 0, 0 );
  360. if ( !l_current_entry->_extended_infos.empty() )
  361. {
  362. for ( auto l_current_extended_info : l_current_entry->_extended_infos )
  363. l_extended_infos.emplace( _wcsdup( l_current_extended_info.first.c_str() ), _wcsdup( l_current_extended_info.second.c_str() ) );
  364. }
  365. break;
  366. }
  367. }
  368. }
  369. if ( l_extended_infos.empty() )
  370. playlist.AppendWithInfo( ptr, title, length * 1000 );
  371. else
  372. playlist.AppendWithInfo( ptr, title, length * 1000, l_extended_infos );
  373. }
  374. ptr += wcslen(ptr) + 1;
  375. }
  376. }
  377. else if (sourceType == ML_TYPE_ITEMRECORDLIST || sourceType == ML_TYPE_CDTRACKS)
  378. {
  379. itemRecordList *obj = (itemRecordList *)data;
  380. wchar_t title[FILETITLE_SIZE] = {0};
  381. for (int x = 0; x < obj->Size; x ++)
  382. {
  383. BuildTitle(&obj->Items[x], title, FILETITLE_SIZE);
  384. playlist.AppendWithInfo(AutoWide(obj->Items[x].filename), title, obj->Items[x].length*1000);
  385. }
  386. }
  387. else if (sourceType == ML_TYPE_ITEMRECORDLISTW)
  388. {
  389. itemRecordListW *obj = (itemRecordListW *)data;
  390. wchar_t title[FILETITLE_SIZE] = {0};
  391. for (int x = 0; x < obj->Size; x ++)
  392. {
  393. BuildTitleW(&obj->Items[x], title, FILETITLE_SIZE);
  394. playlist.AppendWithInfo(obj->Items[x].filename, title, obj->Items[x].length*1000);
  395. }
  396. }
  397. else if (sourceType == ML_TYPE_PLAYLIST)
  398. {
  399. mlPlaylist *ptr = (mlPlaylist *)data;
  400. Playlist sentPlaylist;
  401. if (AGAVE_API_PLAYLISTMANAGER->Load(ptr->filename, &sentPlaylist) == PLAYLISTMANAGER_SUCCESS)
  402. {
  403. playlist.AppendPlaylist(sentPlaylist);
  404. }
  405. }
  406. else if (sourceType == ML_TYPE_PLAYLISTS)
  407. {
  408. mlPlaylist **playlists= (mlPlaylist **)data;
  409. while(playlists && *playlists)
  410. {
  411. mlPlaylist *ptr = *playlists;
  412. Playlist sentPlaylist;
  413. if (AGAVE_API_PLAYLISTMANAGER->Load(ptr->filename, &sentPlaylist) == PLAYLISTMANAGER_SUCCESS)
  414. {
  415. playlist.AppendPlaylist(sentPlaylist);
  416. }
  417. playlists++;
  418. }
  419. }
  420. AGAVE_API_PLAYLISTMANAGER->Save(p.GetFilename(), &playlist);
  421. p.SetSize(playlist.GetNumItems());
  422. p.IssueSaveCallback();
  423. playlist_Reload();
  424. }
  425. }
  426. int playlists_OnDropTarget(int id, int sourceType, INT_PTR data)
  427. {
  428. if (id == playlistsTreeId)
  429. {
  430. switch (sourceType)
  431. {
  432. case ML_TYPE_FILENAMES:
  433. case ML_TYPE_STREAMNAMES:
  434. if (data)
  435. AddPlaylistFromFilenames((const char *)data, 0, 1);
  436. return 1;
  437. case ML_TYPE_FILENAMESW:
  438. case ML_TYPE_STREAMNAMESW:
  439. if (data)
  440. AddPlaylistFromFilenamesW((const wchar_t *)data, 0, 1);
  441. return 1;
  442. case ML_TYPE_ITEMRECORDLIST:
  443. case ML_TYPE_CDTRACKS:
  444. if (data)
  445. AddPlaylistFromItemRecordList((itemRecordList *)data, 0, 1);
  446. return 1;
  447. case ML_TYPE_ITEMRECORDLISTW:
  448. if (data)
  449. AddPlaylistFromItemRecordListW((itemRecordListW *)data, 0, 1);
  450. return 1;
  451. default:
  452. return -1;
  453. }
  454. }
  455. else if (FindTreeItem(id))
  456. {
  457. switch (sourceType)
  458. {
  459. case ML_TYPE_FILENAMES:
  460. case ML_TYPE_STREAMNAMES:
  461. case ML_TYPE_FILENAMESW:
  462. case ML_TYPE_STREAMNAMESW:
  463. case ML_TYPE_ITEMRECORDLIST:
  464. case ML_TYPE_ITEMRECORDLISTW:
  465. case ML_TYPE_CDTRACKS:
  466. if (data && !we_are_drag_and_dropping)
  467. {
  468. AddToPlaylist(tree_to_guid_map[id], sourceType, data);
  469. }
  470. return 1;
  471. default:
  472. return -1;
  473. }
  474. }
  475. return 0;
  476. }
  477. static INT_PTR CALLBACK SelectPlaylistProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  478. {
  479. switch (msg)
  480. {
  481. case WM_INITDIALOG:
  482. {
  483. LRESULT index = SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_ADDSTRING, 0, (LPARAM) WASABI_API_LNGSTRINGW(IDS_SENDTO_NEW_PLAYLIST));
  484. SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_SETITEMDATA , index, -1);
  485. /*if (playlists_CloudAvailable())
  486. {
  487. index = SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_ADDSTRING, 0, (LPARAM) WASABI_API_LNGSTRINGW(IDS_SENDTO_NEW_CLOUD_PLAYLIST));
  488. SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_SETITEMDATA , index, -1);
  489. }*/
  490. AutoLockT<api_playlists> lock (AGAVE_API_PLAYLISTS);
  491. sendto_playlistGUIDs.clear();
  492. size_t count = AGAVE_API_PLAYLISTS->GetCount();
  493. for (size_t i = 0;i != count; i++)
  494. {
  495. PlaylistInfo info(i);
  496. if (info.Valid())
  497. {
  498. sendto_playlistGUIDs.push_back(info.playlist_guid);
  499. if (sendToIgnoreID != info.treeId)
  500. {
  501. index = SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_ADDSTRING, 0, (LPARAM)info.GetName());
  502. SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_SETITEMDATA , index, i);
  503. }
  504. }
  505. }
  506. SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_SETCURSEL, 0, 0);
  507. }
  508. break;
  509. case WM_COMMAND:
  510. switch (LOWORD(wParam))
  511. {
  512. case IDOK:
  513. {
  514. int selection = SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_GETCURSEL, 0, 0);
  515. if (selection != CB_ERR)
  516. EndDialog(hwndDlg, SendDlgItemMessage(hwndDlg, IDC_PLAYLISTS, CB_GETITEMDATA , selection, 0));
  517. else
  518. EndDialog(hwndDlg, -2);
  519. }
  520. break;
  521. case IDCANCEL:
  522. {
  523. EndDialog(hwndDlg, -2);
  524. }
  525. break;
  526. }
  527. break;
  528. }
  529. return 0;
  530. }
  531. int playlists_OnSendTo(int sourceType, INT_PTR data, int id)
  532. {
  533. if (id == playlistsTreeId || id == playlistsCloudTreeId)
  534. {
  535. if (g_config->ReadInt(L"pl_send_to", DEFAULT_PL_SEND_TO))
  536. {
  537. int is_cloud = (id == playlistsCloudTreeId) || (id == playlistsTreeId && g_config->ReadInt(L"cloud", 1));
  538. switch (sourceType)
  539. {
  540. case ML_TYPE_FILENAMES:
  541. case ML_TYPE_STREAMNAMES:
  542. AddPlaylistFromFilenames((const char *)data, 0, MAKELONG(1, is_cloud));
  543. return 1;
  544. case ML_TYPE_FILENAMESW:
  545. case ML_TYPE_STREAMNAMESW:
  546. AddPlaylistFromFilenamesW((const wchar_t *)data, 0, MAKELONG(1, is_cloud));
  547. return 1;
  548. case ML_TYPE_ITEMRECORDLIST:
  549. case ML_TYPE_CDTRACKS:
  550. AddPlaylistFromItemRecordList((itemRecordList *)data, 0, MAKELONG(1, is_cloud));
  551. return 1;
  552. case ML_TYPE_ITEMRECORDLISTW:
  553. AddPlaylistFromItemRecordListW((itemRecordListW *)data, 0, MAKELONG(1, is_cloud));
  554. return 1;
  555. case ML_TYPE_PLAYLIST:
  556. {
  557. mlPlaylist *ptr = (mlPlaylist *)data;
  558. AddPlaylistFromFilenamesW(ptr->filename, 0, MAKELONG(1, is_cloud));
  559. return 1;
  560. }
  561. case ML_TYPE_PLAYLISTS:
  562. {
  563. mlPlaylist **playlists= (mlPlaylist **)data;
  564. while(playlists && *playlists)
  565. {
  566. mlPlaylist *ptr = *playlists;
  567. AddPlaylistFromFilenamesW(ptr->filename, 0, MAKELONG(1, is_cloud));
  568. playlists++;
  569. }
  570. return 1;
  571. }
  572. }
  573. }
  574. else
  575. {
  576. size_t selection = WASABI_API_DIALOGBOXW(IDD_SELECT_PLAYLIST, NULL, SelectPlaylistProc);
  577. if (selection == -2)
  578. return -1;
  579. else if (selection == -1)
  580. {
  581. switch (sourceType)
  582. {
  583. case ML_TYPE_FILENAMES:
  584. case ML_TYPE_STREAMNAMES:
  585. AddPlaylistFromFilenames((const char *)data, 0, true);
  586. return 1;
  587. case ML_TYPE_FILENAMESW:
  588. case ML_TYPE_STREAMNAMESW:
  589. AddPlaylistFromFilenamesW((const wchar_t *)data, 0, true);
  590. return 1;
  591. case ML_TYPE_ITEMRECORDLIST:
  592. case ML_TYPE_CDTRACKS:
  593. AddPlaylistFromItemRecordList((itemRecordList *)data, 0, 1);
  594. return 1;
  595. case ML_TYPE_ITEMRECORDLISTW:
  596. AddPlaylistFromItemRecordListW((itemRecordListW *)data, 0, 1);
  597. return 1;
  598. case ML_TYPE_PLAYLIST:
  599. {
  600. mlPlaylist *ptr = (mlPlaylist *)data;
  601. AddPlaylistFromFilenamesW(ptr->filename, 0, true);
  602. return 1;
  603. }
  604. case ML_TYPE_PLAYLISTS:
  605. {
  606. mlPlaylist **playlists= (mlPlaylist **)data;
  607. while(playlists && *playlists)
  608. {
  609. mlPlaylist *ptr = *playlists;
  610. AddPlaylistFromFilenamesW(ptr->filename, 0, true);
  611. playlists++;
  612. }
  613. return 1;
  614. }
  615. }
  616. }
  617. else if (selection >= 0 && selection < sendto_playlistGUIDs.size())
  618. {
  619. AddToPlaylist(sendto_playlistGUIDs[selection], sourceType, data);
  620. return 1;
  621. }
  622. }
  623. }
  624. else
  625. {
  626. size_t x = id - reinterpret_cast<size_t>(pluginMessageProc);
  627. if (x < sendto_playlistGUIDs.size())
  628. {
  629. AddToPlaylist(sendto_playlistGUIDs[x], sourceType, data);
  630. return 1;
  631. }
  632. }
  633. return 0;
  634. }