12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714 |
- //#define _WIN32_WINNT 0x0400
- #include "../Winamp/buildType.h"
- #include "main.h"
- #include "DeviceView.h"
- //#include <commctrl.h>
- #include "nu/AutoWide.h"
- #include "nu/AutoChar.h"
- #include "../nu/AutoUrl.h"
- #include "SkinnedListView.h"
- #include "../playlist/api_playlistmanager.h"
- #include "../playlist/ifc_playlistdirectorycallback.h"
- #include "../playlist/ifc_playlistloadercallback.h"
- #include "api__ml_pmp.h"
- #include <shlwapi.h>
- #include <time.h>
- #include "metadata_utils.h"
- #include "../ml_wire/ifc_podcast.h"
- #include "./local_menu.h"
- #include "IconStore.h"
- #include "../devices/ifc_deviceevent.h"
- #include "metadata_utils.h"
- #include "../nu/sort.h"
- #include "resource1.h"
- #include <strsafe.h>
- #include "../nu/MediaLibraryInterface.h"
- extern C_ItemList devices;
- extern C_Config * global_config;
- extern INT_PTR CALLBACK pmp_artistalbum_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
- extern INT_PTR CALLBACK pmp_playlist_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
- int IPC_GET_CLOUD_HINST = -1, IPC_LIBRARY_PLAYLISTS_REFRESH = -1;
- HINSTANCE cloud_hinst = 0;
- int currentViewedPlaylist=0;
- HNAVITEM cloudQueueTreeItem=NULL;
- LinkedQueue cloudTransferQueue, cloudFinishedTransfers;
- int cloudTransferProgress = 0;
- DeviceView * currentViewedDevice=NULL;
- volatile size_t TransferContext::paused_all = 0;
- extern void UpdateTransfersListView(bool softUpdate, CopyInst * item=NULL);
- extern void UpdateDevicesListView(bool softUpdate);
- extern INT_PTR CALLBACK config_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
- extern HWND mainMessageWindow;
- extern prefsDlgRecW prefsPage;
- extern int prefsPageLoaded;
- static int thread_id;
- static bool copySettings(wchar_t * ssrc, wchar_t * sdest);
- static __int64 fileSize(wchar_t * filename);
- static void removebadchars(wchar_t *s);
- extern ThreadID *transfer_thread;
- int TransferThreadPoolFunc(HANDLE handle, void *user_data, intptr_t id);
- INT_PTR CALLBACK pmp_queue_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
- INT_PTR CALLBACK pmp_video_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
- DeviceView::DeviceView(Device *dev)
- : activityRunning(FALSE), navigationItemCreated(FALSE), usedSpace(0), totalSpace(0)
- {
- memset(name, 0, sizeof(name));
- queueActiveIcon = isCloudDevice = 0;
- treeItem = videoTreeItem = queueTreeItem = 0;
- connection_type = "USB";
- display_type = "Portable Media Player";
- metadata_fields = (int)dev->extraActions(DEVICE_SUPPORTED_METADATA,0,0,0);
- if(!metadata_fields)
- metadata_fields = -1;
- dev->extraActions(DEVICE_GET_CONNECTION_TYPE, (intptr_t)&connection_type, 0, 0);
- isCloudDevice = (!lstrcmpiA(connection_type, "cloud"));
- dev->extraActions(DEVICE_GET_DISPLAY_TYPE, (intptr_t)&display_type, 0, 0);
- ref_count = 1;
- if (dev->extraActions(DEVICE_GET_UNIQUE_ID, (intptr_t)name, sizeof(name), 0) == 0)
- {
- // fallback
- GUID name_guid;
- CoCreateGuid(&name_guid);
- StringCbPrintfA(name, sizeof(name), "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
- (int)name_guid.Data1, (int)name_guid.Data2, (int)name_guid.Data3,
- (int)name_guid.Data4[0], (int)name_guid.Data4[1],
- (int)name_guid.Data4[2], (int)name_guid.Data4[3],
- (int)name_guid.Data4[4], (int)name_guid.Data4[5],
- (int)name_guid.Data4[6], (int)name_guid.Data4[7] );
- }
- wchar_t inifile[MAX_PATH] = {0};
- dev->extraActions(DEVICE_GET_INI_FILE,(intptr_t)inifile,0,0);
- if(!inifile[0])
- {
- wchar_t name[256] = {0};
- dev->getPlaylistName(0,name,256);
- removebadchars(name);
- // build this slow so we make sure each directory exists
- PathCombine(inifile, WASABI_API_APP->path_getUserSettingsPath(), L"Plugins");
- CreateDirectory(inifile, NULL);
- PathAppend(inifile, L"ml");
- CreateDirectory(inifile, NULL);
- wchar_t ini_filespec[MAX_PATH] = {0};
- StringCchPrintf(ini_filespec, MAX_PATH, L"ml_pmp_device_%s.ini",name);
- PathAppend(inifile, ini_filespec);
- }
- if(fileSize(inifile) <= 0) copySettings(global_config->GetIniFile(),inifile); // import old settings
- config = new C_Config(inifile,L"ml_pmp",global_config);
- currentTransferProgress = 0;
- transferRate=0;
- commitNeeded=false;
- this->dev = dev;
- wchar_t deviceName[256]=L"";
- dev->getPlaylistName(0,deviceName,sizeof(deviceName)/sizeof(wchar_t));
- if (!isCloudDevice) videoView = config->ReadInt(L"showVideoView",dev->extraActions(DEVICE_SUPPORTS_VIDEO,0,0,0));
- else videoView = 0;
- prefsDlgRecW *parentPrefs = (prefsDlgRecW *)dev->extraActions(DEVICE_GET_PREFS_PARENT, 0, 0, 0);
- if (!parentPrefs)
- {
- // only add it when we're using our own root page, otherwise skip this
- if (!prefsPageLoaded)
- {
- SendMessage(plugin.hwndWinampParent,WM_WA_IPC,(intptr_t)&prefsPage,IPC_ADD_PREFS_DLGW);
- }
- prefsPageLoaded+=1;
- }
- if (lstrcmpi(deviceName, L"all_sources"))
- {
- devPrefsPage.hInst=WASABI_API_LNG_HINST;
- devPrefsPage.where=(parentPrefs ? (intptr_t)parentPrefs : (intptr_t)&prefsPage);
- devPrefsPage.dlgID=IDD_CONFIG;
- devPrefsPage.name=_wcsdup(deviceName);
- devPrefsPage.proc=config_dlgproc;
- SendMessage(plugin.hwndWinampParent,WM_WA_IPC,(intptr_t)&devPrefsPage,IPC_ADD_PREFS_DLGW);
- }
- else
- {
- memset(&devPrefsPage, 0, sizeof(prefsDlgRecW));
- }
- UpdateSpaceInfo(TRUE, FALSE);
- threadKillswitch = 0;
- transferContext.transfer_thread = WASABI_API_THREADPOOL->ReserveThread(api_threadpool::FLAG_LONG_EXECUTION);
- transferContext.dev = this;
- WASABI_API_THREADPOOL->AddHandle(transferContext.transfer_thread, transferContext.notifier, TransferThreadPoolFunc, &transferContext, thread_id, api_threadpool::FLAG_LONG_EXECUTION);
- thread_id++;
- if (AGAVE_API_DEVICEMANAGER)
- {
- ifc_device *registered_device = this;
- AGAVE_API_DEVICEMANAGER->DeviceRegister(®istered_device, 1);
- }
- //hTransferThread = CreateThread(NULL, 0, ThreadFunc_Transfer, (LPVOID)this, 0, &dwThreadId);
- /*
- if(dev->getDeviceCapacityTotal() > L3000000000) SyncConnectionDefault=1;
- else SyncConnectionDefault=2;
- */
- SyncConnectionDefault=0; // default off for now.
- if (!isCloudDevice)
- {
- // ok all started. Now do any "on connect" actions...
- time_t lastSync = (time_t)config->ReadInt(L"syncOnConnect_time",0);
- time_t now = time(NULL);
- //int diff = now - lastSync;
- double diff = difftime(now,lastSync);
- config->WriteInt(L"syncOnConnect_time",(int)now);
- if(diff > config->ReadInt(L"syncOnConnect_hours",12)*3600)
- {
- switch(config->ReadInt(L"syncOnConnect",SyncConnectionDefault))
- {
- case 1:
- {
- if (!isCloudDevice) Sync(true);
- //else CloudSync(true);
- }
- break;
- case 2: Autofill(); break;
- }
- }
- }
- if (!AGAVE_API_DEVICEMANAGER)
- RegisterViews(0);
- }
- HNAVITEM GetNavigationRoot(BOOL forceCreate);
- HNAVITEM NavigationItem_Find(HNAVITEM root, const wchar_t *name, BOOL allow_root = 0);
- void DeviceView::RegisterViews(HNAVITEM parent)
- {
- NAVINSERTSTRUCT nis = {0};
- NAVITEM *item = 0;
- wchar_t buffer[128] = {0};
- item = &nis.item;
- if(!parent)
- {
- MLTREEIMAGE devIcon;
- wchar_t deviceName[256]=L"";
- devIcon.resourceId = IDR_DEVICE_ICON;
- devIcon.hinst = plugin.hDllInstance;
- dev->extraActions(DEVICE_SET_ICON,(intptr_t)&devIcon,0,0);
- dev->getPlaylistName(0,deviceName,sizeof(deviceName)/sizeof(wchar_t));
- nis.hParent = GetNavigationRoot(TRUE);
- nis.hInsertAfter = NCI_LAST;
- item->cbSize = sizeof(NAVITEM);
- item->mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_STYLE | NIMF_IMAGE | NIMF_IMAGESEL;
- item->pszText = deviceName;
- item->pszInvariant = nis.item.pszText;
- item->style = NIS_HASCHILDREN;
- item->styleMask = item->style,
- item->iImage = icon_store.GetResourceIcon(devIcon.hinst, MAKEINTRESOURCE(devIcon.resourceId));
- item->iSelectedImage = item->iImage;
- treeItem = parent = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
- navigationItemCreated = TRUE;
- }
- else
- {
- treeItem = parent;
- navigationItemCreated = FALSE;
- item->cbSize = sizeof(NAVITEM);
- item->mask = NIMF_STYLE;
- item->hItem = treeItem;
- item->style = NIS_HASCHILDREN;
- item->styleMask = NIS_HASCHILDREN;
- MLNavItem_SetInfo(plugin.hwndLibraryParent, item);
- /* create transfer view */
- // TODO: create this view dynamically
- HNAVITEM cloud = 0;
- if (isCloudDevice)
- {
- cloud = NavigationItem_Find(0, L"cloud_sources", TRUE);
- if (cloud != NULL) parent = cloud;
- }
- #if 0
- int mode = gen_mlconfig->ReadInt(L"txviewpos", 0);
- if (mode == 1)
- {
- nis.hParent = cloud;//parent;
- nis.hInsertAfter = NCI_FIRST;
- }
- else if (mode == 2)
- {
- nis.hParent = NavigationItem_Find(0, L"ml_devices_root", TRUE);
- nis.hInsertAfter = NCI_FIRST;
- }
- #else
- nis.hParent = parent;
- #endif
- item->cbSize = sizeof(NAVITEM);
- item->mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL;
- item->pszText = WASABI_API_LNGSTRINGW_BUF(IDS_TRANSFERS, buffer, 128);
- item->pszInvariant = (isCloudDevice ? L"cloud_transfers" : L"transfers");
- item->iImage = icon_store.GetQueueIcon();
- item->iSelectedImage = nis.item.iImage;
- #if 0
- if (!cloudQueueTreeItem && isCloudDevice)
- {
- NAVINSERTSTRUCT nis2 = {0};
- nis2.item.cbSize = sizeof(NAVITEM);
- nis2.item.pszText = WASABI_API_LNGSTRINGW(IDS_ADD_SOURCE);
- nis2.item.pszInvariant = L"cloud_add_sources";
- nis2.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL | NIMF_STYLE;
- nis2.item.iImage = nis2.item.iSelectedImage = mediaLibrary.AddTreeImageBmp(IDB_TREEITEM_CLOUD_ADD_SOURCE);
- nis2.hParent = parent;
- nis2.hInsertAfter = NCI_FIRST;
- HNAVITEM item = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis2);
- if (mode == 1) nis.hInsertAfter = item;
- queueTreeItem = cloudQueueTreeItem = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
- #if 0
- nis2.item.pszText = L"BYOS";//WASABI_API_LNGSTRINGW(IDS_ADD_SOURCE);
- nis2.item.pszInvariant = L"cloud_byos";
- nis2.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL | NIMF_STYLE;
- nis2.item.iImage = nis2.item.iSelectedImage = mediaLibrary.AddTreeImageBmp(IDB_TREEITEM_CLOUD_ADD_BYOS);
- nis2.hParent = parent;
- nis2.hInsertAfter = nis.hInsertAfter;
- MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis2);
- #endif
- }
- else
- queueTreeItem = cloudQueueTreeItem;
- #endif
- queueTreeItem = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
- }
- /* create video view */
- if (videoView)
- {
- nis.hParent = parent;
- nis.hInsertAfter = NCI_LAST;
- item->cbSize = sizeof(NAVITEM);
- item->mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL;
- item->pszText = WASABI_API_LNGSTRINGW_BUF(IDS_VIDEO, buffer, 128);
- item->pszInvariant = L"video";
- item->iImage = icon_store.GetVideoIcon();
- item->iSelectedImage = nis.item.iImage;
-
- videoTreeItem = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
- }
- else
- videoTreeItem = 0;
- /* create playlists */
- int l = (dev ? dev->getPlaylistCount() : 0);
- for(int i=1; i<l; i++)
- {
- AddPlaylistNode(i);
- }
- }
- DeviceView::~DeviceView()
- {
- if(configDevice == this) SendMessage(plugin.hwndWinampParent,WM_WA_IPC,(intptr_t)&prefsPage,IPC_OPENPREFSTOPAGE);
- // remove it when we're removed what we added
- int lastPrefsPageLoaded = prefsPageLoaded;
- prefsPageLoaded-=1;
- if(lastPrefsPageLoaded == 1)
- {
- SendMessage(plugin.hwndWinampParent,WM_WA_IPC,(intptr_t)&prefsPage,IPC_REMOVE_PREFS_DLG);
- }
- //OutputDebugString(L"device unloading started");
- // get rid of the transfer thread
- threadKillswitch=1;
- transferContext.WaitForKill();
- if(threadKillswitch != 100)
- {
- /*OutputDebugString(L"FUCKO");*/
- }
- SendMessage(plugin.hwndWinampParent,WM_WA_IPC,(intptr_t)&devPrefsPage,IPC_REMOVE_PREFS_DLG);
- free(devPrefsPage.name);
- //OutputDebugString(L"device unloading finished");
- delete config;
- }
- void DeviceView::SetVideoView(BOOL enabled)
- {
- videoView=enabled;
- config->WriteInt(L"showVideoView",videoView);
- if(videoView)
- {
- /* add video before the playlists */
- wchar_t buffer[128] = {0};
- NAVINSERTSTRUCT nis = {0};
- nis.item.cbSize = sizeof(NAVITEM);
- nis.item.pszText = WASABI_API_LNGSTRINGW_BUF(IDS_VIDEO, buffer, 128);
- nis.item.pszInvariant = L"video";
- nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL;
- nis.hParent = treeItem;
- nis.hInsertAfter = NCI_FIRST;
- nis.item.iImage = icon_store.GetVideoIcon();
- nis.item.iSelectedImage = nis.item.iImage;
- videoTreeItem = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
- }
- else
- {
- MLNavCtrl_DeleteItem(plugin.hwndLibraryParent, videoTreeItem);
- videoTreeItem = 0;
- }
- }
- static void removebadchars(wchar_t *s)
- {
- while (s && *s)
- {
- if (*s == L'?' || *s == L'/' || *s == L'\\' || *s == L':' || *s == L'*' || *s == L'\"' || *s == L'<' || *s == L'>' || *s == L'|')
- *s = L'_';
- s = CharNextW(s);
- }
- }
- static __int64 fileSize(wchar_t * filename)
- {
- WIN32_FIND_DATA f= {0};
- HANDLE h = FindFirstFileW(filename,&f);
- if(h == INVALID_HANDLE_VALUE) return -1;
- FindClose(h);
- ULARGE_INTEGER i;
- i.HighPart = f.nFileSizeHigh;
- i.LowPart = f.nFileSizeLow;
- return i.QuadPart;
- }
- static bool copySettings(wchar_t * ssrc, wchar_t * sdest)
- {
- FILE * src, * dest;
- src=_wfopen(ssrc,L"rt");
- if(!src) return false;
- dest=_wfopen(sdest,L"wt");
- if(!dest)
- {
- fclose(src); return false;
- }
- wchar_t buf[1024]=L"";
- bool insection=false;
- while(fgetws(buf,1024,src))
- {
- if(buf[0]==L'[' && wcslen(buf)>1) if(buf[wcslen(buf)-2]==L']') insection=false;
- if(wcscmp(&buf[0],L"[ml_pmp]\n")==0) insection=true;
- if(insection) fputws(&buf[0],dest);
- }
- fclose(src);
- fclose(dest);
- return true;
- }
- HNAVITEM DeviceView::AddPlaylistNode(int id)
- {
- NAVINSERTSTRUCT nis = {0};
- wchar_t title[256] = {0}, name[128] = {0};
- dev->getPlaylistName(id, title , ARRAYSIZE(title));
- StringCchPrintf(name, ARRAYSIZE(name), L"ml_pmp_playlist_%d", id);
-
- nis.hParent = treeItem;
- nis.hInsertAfter = NCI_LAST;
- memset(&nis.item, 0, sizeof(nis.item));
- nis.item.cbSize = sizeof(NAVITEM);
- nis.item.pszText = title;
- nis.item.pszInvariant = name;
- nis.item.mask = NIMF_TEXT | NIMF_TEXTINVARIANT | NIMF_IMAGE | NIMF_IMAGESEL | NIMF_STYLE;
- nis.item.iImage = icon_store.GetPlaylistIcon();
- nis.item.iSelectedImage = nis.item.iImage;
- nis.item.style = NIS_ALLOWEDIT;
- nis.item.styleMask = nis.item.style;
-
- HNAVITEM item = MLNavCtrl_InsertItem(plugin.hwndLibraryParent, &nis);
- playlistTreeItems.push_back(item);
- return item;
- }
- int DeviceView::CreatePlaylist(wchar_t * name, bool silent)
- {
- HNAVITEM item;
- int playlistId;
-
- if (NULL == name)
- {
- int count, slot, length;
- wchar_t buffer[512] = {0}, buffer2[ARRAYSIZE(buffer)] = {0};
- BOOL foundMatch;
- name = WASABI_API_LNGSTRINGW_BUF(IDS_NEW_PLAYLIST, buffer, ARRAYSIZE(buffer));
- count = dev->getPlaylistCount();
- slot = 1;
- length = -1;
- do
- {
- foundMatch = FALSE;
- for (int i = 1; i < count; i++)
- {
-
- dev->getPlaylistName(i, buffer2, ARRAYSIZE(buffer2));
- if (CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, buffer2, -1, name, -1))
- {
- foundMatch = TRUE;
-
- if(name != buffer)
- {
- if (FAILED(StringCchCopy(buffer, ARRAYSIZE(buffer), name)))
- return -1;
- }
- if (-1 == length)
- {
- wchar_t *end;
- length = lstrlen(buffer);
- end = buffer + length;
-
- if(length > 2 && L')' == *(--end))
- {
- unsigned short charType;
- for(wchar_t *begin = --end; begin != buffer; begin--)
- {
- if (L'(' == *begin)
- {
- if (begin > buffer && L' ' == *(--begin))
- {
- length = (int)(intptr_t)(begin - buffer);
- slot = 0;
- }
- break;
- }
- else if (FALSE == GetStringTypeW(CT_CTYPE1, begin, 1, &charType) ||
- 0 == (C1_DIGIT & charType))
- {
- break;
- }
- }
- }
- }
-
- slot++;
- if (1 == slot)
- buffer[length] = L'\0';
- else if (FAILED(StringCchPrintf(buffer + length, ARRAYSIZE(buffer) - length, L" (%d)", slot)))
- return false;
-
- break;
- }
- }
- } while(FALSE != foundMatch);
- }
- playlistId = dev->newPlaylist(name);
- if(playlistId == -1)
- return -1; // failed
-
- item = AddPlaylistNode(playlistId);
- if (NULL == item)
- {
- dev->deletePlaylist(playlistId);
- return -1;
- }
- DevicePropertiesChanges();
- if(!silent)
- MLNavItem_EditTitle(plugin.hwndLibraryParent, item);
-
- return playlistId;
- }
- void DeviceView::RenamePlaylist(int playlistId)
- {
- HNAVITEM item;
- item = NULL;
- if (0 == playlistId)
- {
- if (0 != dev->extraActions(DEVICE_CAN_RENAME_DEVICE,0,0,0))
- item = treeItem;
- }
- else
- {
- if (playlistId > 0 && playlistId <= (int)playlistTreeItems.size())
- item = playlistTreeItems[playlistId - 1];
- }
-
- if (NULL != item)
- MLNavItem_EditTitle(plugin.hwndLibraryParent, item);
- }
- size_t DeviceView::GetPlaylistName(wchar_t *buffer, size_t bufferSize, int playlistId,
- const wchar_t *defaultName, BOOL quoteSpaces)
- {
- size_t length;
- if (NULL == buffer || 0 == bufferSize)
- return 0;
- buffer[0] = L'\0';
- if (NULL != dev)
- dev->getPlaylistName(playlistId, buffer, bufferSize);
- if (FAILED(StringCchLength(buffer, bufferSize, &length)))
- return 0;
-
- if (0 == length)
- {
- if (NULL != defaultName)
- {
- if (FALSE != IS_INTRESOURCE(defaultName))
- WASABI_API_LNGSTRINGW_BUF((int)(intptr_t)defaultName, buffer, bufferSize);
- else
- {
- if (FAILED(StringCchCopy(buffer, bufferSize, defaultName)))
- return 0;
- }
- if (FAILED(StringCchLength(buffer, bufferSize, &length)))
- return 0;
- }
- }
- else
- {
- if (FALSE != quoteSpaces &&
- (L' ' == buffer[0] || L' ' == buffer[length-1]) &&
- (bufferSize - length) > 2)
- {
- memmove(buffer + 1, buffer, sizeof(wchar_t) * length);
- buffer[0] = L'\"';
- buffer[length++] = L'\"';
- buffer[length] = L'\0';
- }
- }
- return length;
- }
- bool DeviceView::DeletePlaylist(int playlistId, bool deleteFiles, bool verbal)
- {
- int index;
- C_ItemList delList;
-
- if(playlistId < 1)
- return false;
- index = playlistId - 1;
-
- if (false != deleteFiles)
- {
- int length;
- length = dev->getPlaylistLength(playlistId);
- for(int i = 0; i < length; i++)
- {
- delList.Add((void*)dev->getPlaylistTrack(playlistId, i));
- }
- }
- if (false != verbal)
- {
- wchar_t message[1024] = {0}, title[1024] = {0}, playlistName[256] = {0}, deviceName[256] = {0};
- GetPlaylistName(playlistName, ARRAYSIZE(playlistName), playlistId, NULL, FALSE);
- GetPlaylistName(deviceName, ARRAYSIZE(deviceName), 0, MAKEINTRESOURCE(IDS_DEVICE_LOWERCASE), TRUE);
- if (0 != delList.GetSize())
- {
- WASABI_API_LNGSTRINGW_BUF(IDS_PHYSICALLY_REMOVE_X_TRACKS, title, ARRAYSIZE(title));
- StringCchPrintf(message, ARRAYSIZE(message), title, delList.GetSize(), playlistName);
- WASABI_API_LNGSTRINGW_BUF(IDS_DELETE_PLAYLIST_TITLE, title, ARRAYSIZE(title));
- }
- else
- {
- WASABI_API_LNGSTRINGW_BUF(IDS_DELETE_PLAYLIST, title, ARRAYSIZE(title));
- StringCchPrintf(message, ARRAYSIZE(message), title, playlistName, deviceName);
- WASABI_API_LNGSTRINGW_BUF(IDS_DELETE_PLAYLIST_TITLE, title, ARRAYSIZE(title));
- }
-
- if(IDYES != MessageBox(plugin.hwndLibraryParent, message, title,
- MB_YESNO | MB_ICONWARNING))
- {
- return false;
- }
- }
- if (0 != delList.GetSize())
- {
- int result;
- result = DeleteTracks(&delList, CENTER_OVER_ML_VIEW);
- if (IDABORT == result) /* user abort */
- return false;
- if (IDOK != result) /* error */
- {
-
- }
- }
-
- HNAVITEM item = playlistTreeItems[index];
- playlistTreeItems.erase(playlistTreeItems.begin() + index);
- MLNavCtrl_DeleteItem(plugin.hwndLibraryParent, item);
-
- dev->deletePlaylist(playlistId);
- DevicePropertiesChanges();
- return true;
- }
- bool DeviceView::GetTransferFromMlSupported(int dataType)
- {
- switch(dataType)
- {
- case ML_TYPE_ITEMRECORDLISTW:
- case ML_TYPE_ITEMRECORDLIST:
- case ML_TYPE_PLAYLIST:
- case ML_TYPE_PLAYLISTS:
- case ML_TYPE_FILENAMES:
- case ML_TYPE_FILENAMESW:
- return true;
- }
- return false;
- }
- intptr_t DeviceView::TransferFromML(int type, void* data, int unsupportedReturn, int supportedReturn, int playlist)
- {
- int r;
- if (AGAVE_API_STATS)
- {
- wchar_t device_name[128] = {0};
- if(dev->extraActions(DEVICE_GET_MODEL, (intptr_t)device_name, 128, 0) == 1 && device_name[0])
- {
- AGAVE_API_STATS->SetString("pmp", device_name);
- }
- }
- if(type == ML_TYPE_ITEMRECORDLISTW)
- {
- r=AddItemListToTransferQueue((itemRecordListW*)data,playlist);
- }
- else if(type == ML_TYPE_ITEMRECORDLIST)
- {
- itemRecordListW list= {0};
- convertRecordList(&list,(itemRecordList*)data);
- r=AddItemListToTransferQueue(&list,playlist);
- freeRecordList(&list);
- }
- else if(type == ML_TYPE_FILENAMES)
- {
- C_ItemList fileList;
- char * filenames = (char *)data;
- while(filenames && *filenames)
- {
- fileList.Add(filenames);
- filenames+=strlen(filenames)+1;
- }
- r=AddFileListToTransferQueue((char**)fileList.GetAll(),fileList.GetSize(),playlist);
- }
- else if(type == ML_TYPE_FILENAMESW)
- {
- C_ItemList fileList;
- wchar_t * filenames = (wchar_t *)data;
- while(filenames && *filenames)
- {
- fileList.Add(filenames);
- filenames+=wcslen(filenames)+1;
- }
- r=AddFileListToTransferQueue((wchar_t**)fileList.GetAll(),fileList.GetSize(),playlist);
- }
- else if(type == ML_TYPE_PLAYLIST)
- {
- mlPlaylist * pl = (mlPlaylist *)data;
- TransferPlaylist((wchar_t*)pl->filename,(wchar_t*)pl->title);
- r=0;
- }
- else if(type == ML_TYPE_PLAYLISTS)
- {
- mlPlaylist **playlists = (mlPlaylist **)data;
- while(playlists && *playlists)
- {
- mlPlaylist *pl = *playlists;
- TransferPlaylist((wchar_t*)pl->filename,(wchar_t*)pl->title);
- playlists++;
- }
- r=0;
- }
- else return unsupportedReturn;
- wchar_t errStr[32] = {0};
- if(r==-1)
- MessageBox(plugin.hwndLibraryParent,
- WASABI_API_LNGSTRINGW(IDS_DEVICE_OUT_OF_SPACE),
- WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,errStr,32),0);
- else if(r==-2)
- MessageBox(plugin.hwndLibraryParent,
- WASABI_API_LNGSTRINGW(IDS_INCOMPATABLE_FORMAT_NO_TX),
- WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,errStr,32),0);
- return supportedReturn;
- }
- class ItemListRefLoader : public ifc_playlistloadercallback
- {
- public:
- ItemListRefLoader(C_ItemList &itemList, C_ItemList &playlistItemList) : fileList(itemList), playlistList(playlistItemList)
- {
- }
- void OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info)
- {
- if(playlistManager->CanLoad(filename))
- playlistList.Add(_wcsdup(filename));
- else
- fileList.Add(_wcsdup(filename));
- }
- C_ItemList &fileList, &playlistList;
- protected:
- RECVS_DISPATCH;
- };
- #define CBCLASS ItemListRefLoader
- START_DISPATCH;
- VCB( IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile )
- END_DISPATCH;
- #undef CBCLASS
- class PlaylistDirectoryCallback : public ifc_playlistdirectorycallback
- {
- public:
- PlaylistDirectoryCallback(const wchar_t *_extlist) : extlist(_extlist)
- {
- }
- bool ShouldRecurse(const wchar_t *path)
- {
- // TODO: check for recursion?
- return true;
- }
- bool ShouldLoad(const wchar_t *filename)
- {
- if(playlistManager->CanLoad(filename))
- return true;
- const wchar_t *ext = PathFindExtensionW(filename);
- if(!*ext)
- return false;
- ext++;
- const wchar_t *a = extlist;
- while(a && *a)
- {
- if(!_wcsicmp(a, ext))
- return true;
- a += wcslen(a) + 1;
- }
- return false;
- }
- const wchar_t *extlist;
- protected:
- RECVS_DISPATCH;
- };
- #define CBCLASS PlaylistDirectoryCallback
- START_DISPATCH;
- CB(IFC_PLAYLISTDIRECTORYCALLBACK_SHOULDRECURSE, ShouldRecurse)
- CB(IFC_PLAYLISTDIRECTORYCALLBACK_SHOULDLOAD, ShouldLoad)
- END_DISPATCH;
- #undef CBCLASS
- intptr_t DeviceView::TransferFromDrop(HDROP hDrop, int playlist)
- {
- // benski> ugh. memory allocation hell. oh well
- C_ItemList fileList;
- C_ItemList playlistList;
- const wchar_t *extListW = (const wchar_t *)SendMessageW(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GET_EXTLISTW);
- PlaylistDirectoryCallback dirCB(extListW);
- wchar_t temp[2048] = {0};
- int y = DragQueryFileW(hDrop, 0xffffffff, temp, 2048);
- for(int x = 0; x < y; x ++)
- {
- DragQueryFileW(hDrop, x, temp, 2048);
- // see if it's a directory
- bool isDir=false;
- if(!PathIsURLW(temp) && !PathIsNetworkPathW(temp))
- {
- HANDLE h;
- WIN32_FIND_DATAW d;
- h = FindFirstFileW(temp, &d);
- if(h != INVALID_HANDLE_VALUE)
- {
- FindClose(h);
- if(d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- ItemListRefLoader fileListCB(fileList, playlistList);
- playlistManager->LoadDirectory(temp, &fileListCB, &dirCB);
- isDir=true;
- }
- }
- }
- if(!isDir)
- {
- if(playlistManager->CanLoad(temp))
- playlistList.Add(_wcsdup(temp));
- else
- fileList.Add(_wcsdup(temp));
- }
- }
- int r=0, r2=0;
- if(fileList.GetSize())
- r=AddFileListToTransferQueue((wchar_t**)fileList.GetAll(),fileList.GetSize(),playlist);
- #if 0
- if(playlistList.GetSize())
- r2=AddFileListToTransferQueue((wchar_t**)playlistList.GetAll(), playlistList.GetSize(),1/*playlists*/);
- #endif
- wchar_t errStr[32] = {0};
- if(r==-1 || r2==-1)
- MessageBox(plugin.hwndLibraryParent,
- WASABI_API_LNGSTRINGW(IDS_DEVICE_OUT_OF_SPACE),
- WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,errStr,32),0);
- if(r==-2 || r2 == -2)
- MessageBox(plugin.hwndLibraryParent,
- WASABI_API_LNGSTRINGW(IDS_INCOMPATABLE_FORMAT_NO_TX),
- WASABI_API_LNGSTRINGW_BUF(IDS_ERROR,errStr,32),0);
- // benski> my CS301 professor would be proud!
- fileList.for_all(free);
- playlistList.for_all(free);
- GlobalFree((HGLOBAL)extListW);
- return 0;
- }
- HWND DeviceView::CreateView(HWND parent)
- {
- currentViewedDevice=this;
- currentViewedPlaylist=0;
- if (currentViewedDevice->config->ReadInt(L"media_numfilters", 2) == 1)
- return WASABI_API_CREATEDIALOGPARAMW((isCloudDevice ? IDD_VIEW_CLOUD_SIMPLE : IDD_VIEW_PMP_VIDEO),
- parent, pmp_video_dlgproc, (currentViewedDevice->isCloudDevice ? 1 : 2));
- else
- return WASABI_API_CREATEDIALOGPARAMW((isCloudDevice ? IDD_VIEW_CLOUD_ARTISTALBUM : IDD_VIEW_PMP_ARTISTALBUM),
- parent, pmp_artistalbum_dlgproc, 0);
- }
- BOOL DeviceView::DisplayDeviceContextMenu(HNAVITEM item, HWND hostWindow, POINT pt)
- {
- HMENU menu = GetSubMenu(m_context_menus,3);
- if (NULL == menu)
- return FALSE;
- if(dev->extraActions(DEVICE_CAN_RENAME_DEVICE,0,0,0))
- AppendMenu(menu,0,ID_TREEPLAYLIST_RENAMEPLAYLIST,WASABI_API_LNGSTRINGW(IDS_RENAME_DEVICE));
- int r = Menu_TrackSkinnedPopup(menu, TPM_RETURNCMD|TPM_RIGHTBUTTON|TPM_LEFTBUTTON|TPM_NONOTIFY,
- pt.x, pt.y, plugin.hwndLibraryParent, NULL);
- if(dev->extraActions(DEVICE_CAN_RENAME_DEVICE,0,0,0))
- DeleteMenu(menu,ID_TREEPLAYLIST_RENAMEPLAYLIST,MF_BYCOMMAND);
- switch(r)
- {
- case ID_TREEDEVICE_NEWPLAYLIST:
- CreatePlaylist();
- break;
- case ID_TREEDEVICE_EJECTDEVICE:
- Eject();
- break;
- case ID_TREEPLAYLIST_RENAMEPLAYLIST:
- MLNavItem_EditTitle(plugin.hwndLibraryParent, item);
- //RenamePlaylist(0);
- break;
- }
- return TRUE;
- }
- BOOL DeviceView::DisplayPlaylistContextMenu(int playlistId, HNAVITEM item, HWND hostWindow, POINT pt)
- {
- HMENU menu = GetSubMenu(m_context_menus,4);
- if (NULL == menu)
- return FALSE;
-
- EnableMenuItem(menu,ID_TREEPLAYLIST_COPYPLAYLISTTOLOCALMEDIA,
- MF_BYCOMMAND | (dev->copyToHardDriveSupported()? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
- int r = Menu_TrackSkinnedPopup(menu,TPM_RETURNCMD|TPM_RIGHTBUTTON|TPM_LEFTBUTTON|TPM_NONOTIFY,
- pt.x, pt.y, plugin.hwndLibraryParent, NULL);
- switch(r)
- {
- case ID_TREEPLAYLIST_RENAMEPLAYLIST:
- MLNavItem_EditTitle(plugin.hwndLibraryParent, item);
- break;
- case ID_TREEPLAYLIST_REMOVEPLAYLISTANDFILES:
- DeletePlaylist(playlistId, true, true);
- break;
- case ID_TREEPLAYLIST_REMOVEPLAYLIST:
- DeletePlaylist(playlistId, false, true);
- break;
- case ID_TREEPLAYLIST_COPYPLAYLISTTOLOCALMEDIA:
- CopyPlaylistToLibrary(playlistId);
- break;
- }
- return TRUE;
- }
- static HNAVITEM Navigation_GetItemFromMessage(INT msg, INT_PTR param)
- {
- return (msg < ML_MSG_NAVIGATION_FIRST) ?
- MLNavCtrl_FindItemById(plugin.hwndLibraryParent, param) :
- (HNAVITEM)param;
- }
- BOOL DeviceView::Navigation_IsPlaylistItem(HNAVITEM item, int *playlistId)
- {
- for(size_t i=0; i < playlistTreeItems.size(); i++)
- {
- if(item == playlistTreeItems[i])
- {
- if (NULL != playlistId)
- *playlistId = (i + 1);
- return TRUE;
- }
- }
- return FALSE;
- }
- HWND DeviceView::Navigation_CreateViewCb(HNAVITEM item, HWND parentWindow)
- {
- if(item == treeItem)
- {
- if (FALSE != navigationItemCreated)
- {
- currentViewedDevice = this;
- currentViewedPlaylist = 0;
- return WASABI_API_CREATEDIALOGW((currentViewedDevice->isCloudDevice ? IDD_VIEW_CLOUD_ARTISTALBUM : IDD_VIEW_PMP_ARTISTALBUM), parentWindow, pmp_artistalbum_dlgproc);
- }
- }
- else if (item == queueTreeItem)
- {
- currentViewedDevice = this;
- currentViewedPlaylist = 0;
- return WASABI_API_CREATEDIALOGPARAMW((currentViewedDevice->isCloudDevice ? IDD_VIEW_CLOUD_QUEUE : IDD_VIEW_PMP_QUEUE), parentWindow, pmp_queue_dlgproc, (LPARAM)this);
- }
- else if(item == videoTreeItem)
- {
- currentViewedDevice = this;
- currentViewedPlaylist = 0;
- return WASABI_API_CREATEDIALOGPARAMW(IDD_VIEW_PMP_VIDEO, parentWindow, pmp_video_dlgproc, 0);
- }
- else
- {
- if (FALSE != Navigation_IsPlaylistItem(item, ¤tViewedPlaylist))
- {
- currentViewedDevice = this;
- return WASABI_API_CREATEDIALOGW(IDD_VIEW_PMP_PLAYLIST, parentWindow, pmp_playlist_dlgproc);
- }
- }
- return NULL;
- }
- BOOL DeviceView::Navigation_ShowContextMenuCb(HNAVITEM item, HWND hostWindow, POINT pt)
- {
- if (item == treeItem)
- {
- if (FALSE != navigationItemCreated)
- return DisplayDeviceContextMenu(item, hostWindow, pt);
- }
- else
- {
- int playlistId;
- if (FALSE != Navigation_IsPlaylistItem(item, &playlistId))
- return DisplayPlaylistContextMenu(playlistId, item, hostWindow, pt);
- }
- return FALSE;
- }
- BOOL DeviceView::Navigation_ClickCb(HNAVITEM item, int actionType, HWND hostWindow)
- {
- int playlistId;
- switch(actionType)
- {
- case ML_ACTION_DBLCLICK:
- case ML_ACTION_ENTER:
- if (FALSE != Navigation_IsPlaylistItem(item, &playlistId))
- {
- PlayPlaylist(playlistId, false, true, hostWindow);
- return TRUE;
- }
- break;
- }
-
- return FALSE;
- }
- int DeviceView::Navigation_DropTargetCb(HNAVITEM item, unsigned int dataType, void *data)
- {
- if (item == treeItem)
- {
- if (FALSE != navigationItemCreated)
- {
- if(NULL == data)
- return (false != GetTransferFromMlSupported(dataType)) ? 1 : -1;
-
- return TransferFromML(dataType, data, -1, 1);
- }
- }
- else
- {
- int playlistId;
- if (FALSE != Navigation_IsPlaylistItem(item, &playlistId))
- {
- if(NULL == data)
- return (false != GetTransferFromMlSupported(dataType)) ? 1 : -1;
-
- return TransferFromML(dataType, data, -1, 1, playlistId);
- }
- }
- return FALSE;
- }
- BOOL DeviceView::Navigation_TitleEditBeginCb(HNAVITEM item)
- {
- if (item == treeItem)
- {
- if (FALSE != navigationItemCreated &&
- FALSE == dev->extraActions(DEVICE_CAN_RENAME_DEVICE,0,0,0))
- {
- return TRUE;
- }
- }
-
- return FALSE;
- }
- BOOL DeviceView::Navigation_TitleEditEndCb(HNAVITEM item, const wchar_t *title)
- {
- int playlistId = 0;
- wchar_t buffer[512] = {0};
- if (item == treeItem)
- {
- if (FALSE == navigationItemCreated)
- return FALSE;
- playlistId = 0;
- }
- else
- {
- if (FALSE == Navigation_IsPlaylistItem(item, &playlistId))
- return FALSE;
- }
- if (NULL == title)
- return TRUE;
- buffer[0] = L'\0';
- dev->getPlaylistName(playlistId, buffer, ARRAYSIZE(buffer));
-
- if (CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, buffer, -1, title, -1))
- return TRUE;
- dev->setPlaylistName(playlistId, title);
- DevicePropertiesChanges();
- buffer[0] = L'\0';
- dev->getPlaylistName(playlistId, buffer, ARRAYSIZE(buffer));
- if (0 == playlistId)
- {
- free(devPrefsPage.name);
- devPrefsPage.name = _wcsdup(buffer);
- UpdateDevicesListView(false);
- OnNameChanged(buffer);
- }
- if (CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, buffer, -1, title, -1))
- return TRUE;
- NAVITEM itemInfo;
- itemInfo.cbSize = sizeof(itemInfo);
- itemInfo.pszText = buffer;
- itemInfo.hItem = item;
- itemInfo.mask = NIMF_TEXT;
- MLNavItem_SetInfo(plugin.hwndLibraryParent, &itemInfo);
- return FALSE;
- }
- BOOL DeviceView::Navigation_KeyDownCb(HNAVITEM item, NMTVKEYDOWN *keyData, HWND hwnd)
- {
- int playlistId;
- if (item == treeItem)
- {
- if (FALSE == navigationItemCreated)
- return FALSE;
- switch(keyData->wVKey)
- {
- case VK_F2:
- MLNavItem_EditTitle(plugin.hwndLibraryParent, item);
- break;
- }
- return TRUE;
- }
- if (FALSE != Navigation_IsPlaylistItem(item, &playlistId))
- {
- switch(keyData->wVKey)
- {
- case VK_F2:
- MLNavItem_EditTitle(plugin.hwndLibraryParent, item);
- break;
- case VK_DELETE:
- DeletePlaylist(playlistId, false, true);
- break;
- }
- return TRUE;
- }
- return FALSE;
- }
- intptr_t DeviceView::MessageProc(int message_type, intptr_t param1, intptr_t param2, intptr_t param3)
- {
- if(message_type >= ML_MSG_TREE_BEGIN && message_type <= ML_MSG_TREE_END)
- {
- HNAVITEM item;
- switch(message_type)
- {
- case ML_MSG_TREE_ONCREATEVIEW:
- item = Navigation_GetItemFromMessage(message_type, param1);
- return (INT_PTR)Navigation_CreateViewCb(item, (HWND)param2);
- case ML_MSG_NAVIGATION_CONTEXTMENU:
- {
- POINT pt;
- POINTSTOPOINT(pt, MAKEPOINTS(param3));
- item = Navigation_GetItemFromMessage(message_type, param1);
- return (INT_PTR)Navigation_ShowContextMenuCb(item, (HWND)param2, pt);
- }
- case ML_MSG_TREE_ONCLICK:
- item = Navigation_GetItemFromMessage(message_type, param1);
- return (INT_PTR)Navigation_ClickCb(item, (int)param2, (HWND)param3);
- case ML_MSG_TREE_ONDROPTARGET:
- item = Navigation_GetItemFromMessage(message_type, param1);
- return (INT_PTR)Navigation_DropTargetCb(item, (unsigned int)param2, (void*)param3);
- case ML_MSG_NAVIGATION_ONBEGINTITLEEDIT:
- item = Navigation_GetItemFromMessage(message_type, param1);
- return (INT_PTR)Navigation_TitleEditBeginCb(item);
- case ML_MSG_NAVIGATION_ONENDTITLEEDIT:
- item = Navigation_GetItemFromMessage(message_type, param1);
- return (INT_PTR)Navigation_TitleEditEndCb(item, (const wchar_t*)param2);
- case ML_MSG_TREE_ONKEYDOWN:
- item = Navigation_GetItemFromMessage(message_type, param1);
- return (INT_PTR)Navigation_KeyDownCb(item, (NMTVKEYDOWN*)param2, (HWND)param3);
- }
- }
- else if(message_type == ML_MSG_ONSENDTOBUILD)
- {
- if (!gen_mlconfig->ReadInt(L"pmp_send_to", DEFAULT_PMP_SEND_TO))
- {
- if (param1 == ML_TYPE_ITEMRECORDLIST || param1 == ML_TYPE_ITEMRECORDLISTW ||
- param1 == ML_TYPE_FILENAMES || param1 == ML_TYPE_FILENAMESW ||
- param1 == ML_TYPE_PLAYLIST || param1 == ML_TYPE_PLAYLISTS)
- {
- if (dev->extraActions(DEVICE_SENDTO_UNSUPPORTED, 0, 0, 0) == 0)
- {
- wchar_t buffer[128] = {0};
- dev->getPlaylistName(0, buffer, 128);
- mediaLibrary.AddToSendTo(buffer, param2, reinterpret_cast<INT_PTR>(this));
- }
- }
- }
- }
- else if(message_type == ML_MSG_ONSENDTOSELECT && param2 && param3 == (intptr_t)this)
- {
- // TODO!!!
- // if we get a playlist or playlist list and we can match it to a cloud device then
- // we check for 'hss' and if so then process as a cloud playlist else do as before
- if (this->isCloudDevice && (param1 == ML_TYPE_PLAYLIST || param1 == ML_TYPE_PLAYLISTS))
- {
- char name[128] = {0};
- if (dev->extraActions(DEVICE_GET_UNIQUE_ID, (intptr_t)name, sizeof(name), 0))
- {
- if (!strcmp(name, "hss"/*HSS_CLIENT*/))
- {
- if(param1 == ML_TYPE_PLAYLIST)
- {
- mlPlaylist * pl = (mlPlaylist *)param2;
- TransferAddCloudPlaylist((wchar_t*)pl->filename, (wchar_t*)pl->title);
- }
- else if(param1 == ML_TYPE_PLAYLISTS)
- {
- mlPlaylist **playlists = (mlPlaylist **)param2;
- while(playlists && *playlists)
- {
- mlPlaylist *pl = *playlists;
- TransferAddCloudPlaylist((wchar_t*)pl->filename, (wchar_t*)pl->title);
- playlists++;
- }
- }
- return 1;
- }
- }
- }
- UpdateActivityState();
- return TransferFromML(param1,(void*)param2,0,1);
- }
- return 0;
- }
- void DeviceView::DevicePropertiesChanges()
- {
- commitNeeded=true;
- SetEvent(transferContext.notifier);
- }
- void DeviceView::Eject()
- {
- LinkedQueue * txQueue = getTransferQueue(this);
- if(txQueue && txQueue->GetSize() == 0)
- {
- dev->Eject();
- }
- else
- {
- wchar_t titleStr[32] = {0};
- MessageBox(plugin.hwndLibraryParent,WASABI_API_LNGSTRINGW(IDS_SYNC_IS_IN_PROGRESS),
- WASABI_API_LNGSTRINGW_BUF(IDS_CANNOT_EJECT,titleStr,32),0);
- }
- }
- Device * deleteTrackDev;
- C_ItemList * deleteTracks;
- extern HWND hwndMediaView;
- static INT_PTR CALLBACK pmp_delete_progress_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
- {
- static int i;
- static songid_t s;
- switch(uMsg)
- {
- case WM_INITDIALOG:
- i=0;
- s=0;
- SetWindowText(hwndDlg,WASABI_API_LNGSTRINGW((!currentViewedDevice || currentViewedDevice && !currentViewedDevice->isCloudDevice ? IDS_DELETING_TRACKS : IDS_REMOVING_TRACKS)));
- SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETRANGE,0,MAKELPARAM(0, (!deleteTracks ? 0 : deleteTracks->GetSize())));
- SetTimer(hwndDlg,0,5,NULL);
- if (FALSE != CenterWindow(hwndDlg, (HWND)lParam))
- SendMessage(hwndDlg, DM_REPOSITION, 0, 0L);
- break;
- case WM_TIMER:
- if(wParam == 1)
- {
- KillTimer(hwndDlg,wParam);
- SendDlgItemMessage(hwndDlg,IDC_PROGRESS,PBM_SETPOS,i,0);
- if(i < deleteTracks->GetSize())
- {
- songid_t s2 = (songid_t)deleteTracks->Get(i++);
- if(s != s2)
- {
- if(hwndMediaView) SendMessage(hwndMediaView,WM_USER+1,(WPARAM)s2,0);
- deleteTrackDev->deleteTrack(s2);
- s=s2;
- }
- SetTimer(hwndDlg,1,5,NULL);
- }
- else EndDialog(hwndDlg, IDOK);
- }
- else if(wParam == 0)
- {
- KillTimer(hwndDlg,0);
- int s = deleteTracks->GetSize();
- for(int i=0; i<s; i++)
- {
- void * p = deleteTracks->Get(i);
- for(int j=i+1; j<s; j++)
- {
- if(p == deleteTracks->Get(j))
- {
- deleteTracks->Del(j--); s--;
- }
- }
- }
- SetTimer(hwndDlg,1,5,NULL);
- }
- break;
- case WM_COMMAND:
- if(LOWORD(wParam) == IDC_ABORT)
- EndDialog(hwndDlg, IDABORT);
- break;
- }
- return 0;
- }
- int DeviceView::DeleteTracks(C_ItemList * tracks, HWND centerWindow)
- {
- LinkedQueue * txQueue = getTransferQueue(this);
- if(txQueue && txQueue->GetSize() > 0)
- {
- wchar_t sorry[32] = {0};
- MessageBox(plugin.hwndLibraryParent,WASABI_API_LNGSTRINGW(IDS_CANNOT_REMOVE_TRACKS_WHILE_TRANSFERING),
- WASABI_API_LNGSTRINGW_BUF(IDS_SORRY,sorry,32),0);
- return -1;
- }
- if (dev && tracks)
- {
- deleteTrackDev = dev;
- deleteTracks = tracks;
- return WASABI_API_DIALOGBOXPARAMW(IDD_PROGRESS, plugin.hwndLibraryParent, pmp_delete_progress_dlgproc, (LPARAM)centerWindow);
- }
- return IDABORT;
- }
- int DeviceView::AddFileListToTransferQueue(char ** files, int num, int playlist)
- {
- wchar_t ** filesW = (wchar_t**)calloc(num, sizeof(wchar_t*));
- for(int i=0; i<num; i++)
- {
- filesW[i] = AutoWideDup(files[i]);
- }
- int r = AddFileListToTransferQueue(filesW,num,playlist);
- for(int i=0; i<num; i++)
- {
- free(filesW[i]);
- }
- free(filesW);
- return r;
- }
- int DeviceView::AddFileListToTransferQueue(wchar_t ** files, int num, int playlist)
- {
- C_ItemList * irs = fileListToItemRecords(files,num, CENTER_OVER_ML_VIEW);
- int r = AddItemListToTransferQueue(irs,playlist);
- for(int i=0; i < irs->GetSize(); i++)
- {
- itemRecordW * it = (itemRecordW *)irs->Get(i);
- freeRecord(it);
- free(it);
- }
- delete irs;
- return r;
- }
- void TransfersListPushPopItem(CopyInst * item, DeviceView *view);
- int DeviceView::AddItemListToTransferQueue(C_ItemList * items, int playlist)
- {
- if(playlist == 0)
- {
- if (!isCloudDevice)
- {
- int r=0;
- C_ItemList toSend, haveSent;
- ProcessDatabaseDifferences(dev,items,&haveSent,&toSend,NULL,NULL);
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->lock();
- for(int i = 0; i < toSend.GetSize(); i++)
- {
- if((r = this->AddTrackToTransferQueue(this, (itemRecordW*)toSend.Get(i), true)) == -1) break;
- }
-
- txQueue->unlock();
- }
- return r;
- }
- else
- {
- int r=0;
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->lock();
-
- for(int i = 0; i < items->GetSize(); i++)
- {
- if((r = this->AddTrackToTransferQueue(this, (itemRecordW*)items->Get(i), true)) == -1) break;
- }
-
- txQueue->unlock();
- }
- return r;
- }
- }
- else
- {
- return TransferTracksToPlaylist(items,playlist);
- }
- }
- int DeviceView::AddItemListToTransferQueue(itemRecordListW * items, int playlist)
- {
- if(playlist == 0)
- {
- if (!isCloudDevice)
- {
- int r=0;
- C_ItemList toSend;
- ProcessDatabaseDifferences(dev,items,NULL,&toSend,NULL,NULL);
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->lock();
- for (int i = 0; i < toSend.GetSize(); i++)
- if((r = this->AddTrackToTransferQueue(this, (itemRecordW*)toSend.Get(i), true)) == -1) break;
- txQueue->unlock();
- }
- return r;
- }
- else
- {
- int r=0;
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->lock();
- for (int i = 0; i < items->Size; i++)
- if((r = this->AddTrackToTransferQueue(this, &items->Items[i], true)) == -1) break;
- txQueue->unlock();
- }
- return r;
- }
- }
- else
- {
- C_ItemList itemRecords;
- for (int i = 0; i < items->Size; i++) itemRecords.Add(&items->Items[i]);
- return TransferTracksToPlaylist(&itemRecords,playlist);
- }
- }
- class ItemListLoader : public ifc_playlistloadercallback
- {
- public:
- void OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info)
- {
- fileList.Add(_wcsdup(filename));
- }
- void FreeAll()
- {
- fileList.for_all(free);
- }
- C_ItemList fileList;
- protected:
- RECVS_DISPATCH;
- };
- #define CBCLASS ItemListLoader
- START_DISPATCH;
- VCB( IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile )
- END_DISPATCH;
- #undef CBCLASS
- void DeviceView::TransferPlaylist(wchar_t * file, wchar_t * name0)
- {
- // first sort the name out
- if(!file) return;
- wchar_t name[256] = {0};
- if(!name0)
- {
- wchar_t * s = wcsrchr(file,L'\\');
- if(!s) s = wcsrchr(file,L'/');
- if(!s) s = file;
- else s++;
- if(wcslen(s) >= 255) s[255]=0;
- StringCchCopy(name,256, s);
- wchar_t * e = wcsrchr(name,L'.');
- if(e) *e=0;
- }
- else lstrcpyn(name,name0,255);
- name[255]=0;
- // name sorted, parse m3u
- ItemListLoader fileList;
- playlistManager->Load(file, &fileList);
- C_ItemList *itemRecords = fileListToItemRecords(&fileList.fileList, CENTER_OVER_ML_VIEW);
- fileList.FreeAll();
- // now we have a list of itemRecords, lets try and add this playlist to the device!
- int plid = CreatePlaylist(name,true);
- if(plid != -1)
- TransferTracksToPlaylist(itemRecords,plid);
- delete itemRecords;
- }
- int DeviceView::TransferTracksToPlaylist(C_ItemList *itemRecords, int plid)
- {
- wchar_t name[256] = {0};
- dev->getPlaylistName(plid,name,256);
- int i;
- for(i=0; i<itemRecords->GetSize(); i++)
- {
- itemRecordW * ice = (itemRecordW *)itemRecords->Get(i);
- wchar_t num[12] = {0};
- StringCchPrintf(num, 12, L"%x",i);
- setRecordExtendedItem(ice,L"PLN",num);
- }
- C_ItemList irAlreadyOn, siAlreadyOn;
- ProcessDatabaseDifferences(dev,itemRecords,&irAlreadyOn,NULL,&siAlreadyOn,NULL);
- // itemRecords_sort, irAlreadyOn, irTransfer and siAlreadyOn will NOT be in playlist order
- // we must get them into playlist order. In O(n) :/
- int l = itemRecords->GetSize();
- PlaylistAddItem * pl = (PlaylistAddItem*)calloc(l,sizeof(PlaylistAddItem));
- int on=0;
- for(i=0; i < l; i++)
- {
- itemRecordW * ice = (itemRecordW *)itemRecords->Get(i);
- int n;
- swscanf(getRecordExtendedItem(ice,L"PLN"),L"%x",&n);
- if(n >= l)
- {
- continue;
- }
- pl[n].item = ice;
- if(on < irAlreadyOn.GetSize()) if((itemRecordW*)irAlreadyOn.Get(on) == ice) // this track is on the device!
- {
- pl[n].songid = (songid_t)siAlreadyOn.Get(on);
- on++;
- }
- }
- // awesome! pl now contains our playlist in proper order with the "songid" fields set if the track is on the device.
- C_ItemList * directAdd = new C_ItemList;
- int m = 0;
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- PlaylistCopyInst * inst = NULL;
- txQueue->lock();
- for(i=0; i < l; i++)
- {
- if(pl[i].songid)
- {
- directAdd->Add((void*)pl[i].songid);
- }
- else
- {
- int r = dev->trackAddedToTransferQueue(pl[i].item);
- if(r)
- {
- m |= (-r);
- freeRecord(pl[i].item);
- continue;
- }
- if(!inst)
- {
- if(plid != -1) for(int i=0; i<directAdd->GetSize(); i++)
- dev->addTrackToPlaylist(plid,(songid_t)directAdd->Get(i));
- delete directAdd;
- }
- else
- {
- inst->plAddSongs = directAdd;
- AddTrackToTransferQueue(inst);
- }
- directAdd = new C_ItemList;
- inst = new PlaylistCopyInst(this,pl[i].item,name,plid);
- }
- freeRecord(pl[i].item);
- }
- if(inst)
- {
- inst->plAddSongs = directAdd;
- AddTrackToTransferQueue(inst);
- }
- else // NULL inst means no transfers!
- {
- if(plid != -1) for(int i=0; i<directAdd->GetSize(); i++)
- dev->addTrackToPlaylist(plid,(songid_t)directAdd->Get(i));
- delete directAdd;
- }
- txQueue->unlock();
- }
- if (pl) free(pl);
- wchar_t warnStr[32] = {0};
- WASABI_API_LNGSTRINGW_BUF(IDS_WARNING,warnStr,32);
- if(m == 1) MessageBox(plugin.hwndLibraryParent,WASABI_API_LNGSTRINGW(IDS_NATS_DEVICE_MAYBE_FULL),warnStr,0);
- else if(m == 2) MessageBox(plugin.hwndLibraryParent,WASABI_API_LNGSTRINGW(IDS_NATS_SOME_OF_INCOMPATABLE_FORMAT),warnStr,0);
- else if(m == 3) MessageBox(plugin.hwndLibraryParent,WASABI_API_LNGSTRINGW(IDS_NATS_MAYBE_FULL_AND_INCOMPATABLE_FORMAT),warnStr,0);
- return 0;
- }
- void DeviceView::TransferAddCloudPlaylist(wchar_t * file, wchar_t * name0)
- {
- if (!file) return;
- AGAVE_API_PLAYLISTS->Lock();
- for (size_t index = 0; index < AGAVE_API_PLAYLISTS->GetCount(); index++)
- {
- const wchar_t* filename = AGAVE_API_PLAYLISTS->GetFilename(index);
- if (!lstrcmpiW(filename, file))
- {
- int cloud = 1;
- if (AGAVE_API_PLAYLISTS->GetInfo(index, api_playlists_cloud, &cloud, sizeof(cloud)) == API_PLAYLISTS_SUCCESS)
- {
- // not set as a cloud playlist so we need to set and then announce
- if (!cloud)
- {
- cloud = 1;
- AGAVE_API_PLAYLISTS->SetInfo(index, api_playlists_cloud, &cloud, sizeof(cloud));
- AGAVE_API_PLAYLISTS->Flush();
- }
- if (!cloud_hinst) cloud_hinst = (HINSTANCE)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GET_CLOUD_HINST);
- if (cloud_hinst && cloud_hinst != (HINSTANCE)1)
- {
- winampMediaLibraryPlugin *(*gp)();
- gp = (winampMediaLibraryPlugin * (__cdecl *)(void))GetProcAddress(cloud_hinst, "winampGetMediaLibraryPlugin");
- if (gp)
- {
- winampMediaLibraryPlugin *mlplugin = gp();
- if (mlplugin && (mlplugin->version >= MLHDR_VER_OLD && mlplugin->version <= MLHDR_VER))
- {
- mlplugin->MessageProc(0x406, index, 0, 0);
- }
- }
- }
- PostMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_LIBRARY_PLAYLISTS_REFRESH);
- }
- else
- {
- }
- break;
- }
- }
- AGAVE_API_PLAYLISTS->Unlock();
- }
- extern MLTREEITEMW mainTreeItem;
- HWND hwndToolTips=NULL;
- int DeviceView::AddTrackToTransferQueue(CopyInst * inst)
- {
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->Offer(inst);
- if(txQueue->GetSize() == 1)
- SetEvent(transferContext.notifier);
- device_update_map[0] = true;
- device_update_map[inst->dev] = true;
- }
- return 0;
- }
- int DeviceView::AddTrackToTransferQueue(DeviceView * device, itemRecordW * item, bool dupeCheck, bool forceDupe)
- {
- SongCopyInst * inst = new SongCopyInst(device, item);
- if (dupeCheck)
- {
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->lock();
- // current queue dupe check
- for(int i = 0; i < txQueue->GetSize(); i++)
- {
- if(((CopyInst *)txQueue->Get(i))->Equals(inst))
- {
- delete inst;
- txQueue->unlock();
- return 0;
- }
- }
- txQueue->unlock();
- }
- }
- if (!forceDupe)
- {
- int r = dev->trackAddedToTransferQueue(&inst->song);
- if (r)
- {
- if (r == 2)
- {
- inst->status = STATUS_DONE;
- inst->res = 2;
- AddTrackToTransferQueue(inst);
- return 0;
- }
- else
- {
- delete inst;
- }
- }
- else AddTrackToTransferQueue(inst);
- return r;
- }
- else
- {
- inst->res = 2;
- AddTrackToTransferQueue(inst);
- return 0;
- }
- }
- class SyncItemListLoader : public ifc_playlistloadercallback
- {
- public:
- void OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info)
- {
- if(pos < len)
- {
- songs[pos].filename = _wcsdup(filename);
- metaToGet->Add(&songs[pos].map);
- songMaps->Add(&songs[pos].pladd);
- }
- pos++;
- }
- int pos,len;
- songMapping * songs;
- C_ItemList * metaToGet, * songMaps;
- protected:
- RECVS_DISPATCH;
- };
- #define CBCLASS SyncItemListLoader
- START_DISPATCH;
- VCB(IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile)
- END_DISPATCH;
- #undef CBCLASS
- typedef struct
- {
- mlPlaylistInfo info;
- songMapping * songs;
- } SyncPlaylist;
- void TransfersListUpdateItem(CopyInst * item);
- void TransfersListUpdateItem(CopyInst * item, DeviceView *view);
- /*
- static int setPlaylistTrack(Device * dev, int pl, int n, int len, songid_t song) {
- if(n >= len) { while(n >= len) { dev->addTrackToPlaylist(pl,song); len++; } return len; }
- else {
- dev->addTrackToPlaylist(pl,song);
- dev->playlistSwapItems(pl,len,n);
- dev->removeTrackFromPlaylist(pl,len);
- }
- return len;
- }
- */
- class PlaylistSyncCopyInst : public CopyInst
- {
- public:
- bool memFreed;
- C_ItemList *songMaps;
- C_ItemList * playlists;
- PlaylistSyncCopyInst(DeviceView *dev, C_ItemList *songMaps, C_ItemList * playlists) : songMaps(songMaps), playlists(playlists)
- {
- usesPreCopy = false;
- usesPostCopy = true;
- this->dev = dev;
- equalsType = -1;
- status=STATUS_WAITING;
- // status caption
- WASABI_API_LNGSTRINGW_BUF(IDS_WAITING,statusCaption,sizeof(statusCaption)/sizeof(wchar_t));
- // track caption
- WASABI_API_LNGSTRINGW_BUF(IDS_PLAYLIST_SYNCRONIZATION,trackCaption,sizeof(trackCaption)/sizeof(wchar_t));
- // type caption
- WASABI_API_LNGSTRINGW_BUF(IDS_OTHER,typeCaption,sizeof(typeCaption)/sizeof(wchar_t));
- memFreed=false;
- }
- virtual ~PlaylistSyncCopyInst()
- {
- freeMemory();
- }
- virtual bool CopyAction()
- {
- return false;
- }
- virtual void PostCopyAction()
- {
- SyncPlaylists(); freeMemory();
- }
- virtual void Cancelled()
- {
- freeMemory();
- }
- virtual bool Equals(CopyInst * b)
- {
- return false;
- }
- void freeMemory()
- {
- if(memFreed) return;
- memFreed=true;
- if(songMaps) delete songMaps;
- songMaps = NULL;
- if(playlists)
- {
- int l = playlists->GetSize();
- for(int i=0; i<l; i++)
- {
- SyncPlaylist * playlist = (SyncPlaylist *)playlists->Get(i);
- if(playlist)
- {
- if(playlist->songs)
- {
- for(int j=0; j<playlist->info.numItems; j++)
- {
- if(playlist->songs[j].ice)
- {
- freeRecord(playlist->songs[j].ice);
- free(playlist->songs[j].ice);
- }
- if(playlist->songs[j].filename)
- free(playlist->songs[j].filename);
- }
- free(playlist->songs);
- }
- free(playlist);
- }
- }
- delete playlists;
- playlists = NULL;
- }
- }
- void SyncPlaylists()
- {
- if(memFreed)
- return;
- WASABI_API_LNGSTRINGW_BUF(IDS_WORKING,statusCaption,sizeof(statusCaption)/sizeof(wchar_t));
- TransfersListUpdateItem(this);
- TransfersListUpdateItem(this, dev);
- MapItemRecordsToSongs(dev->dev,(PlaylistAddItem **)songMaps->GetAll(),songMaps->GetSize());
- int numPlaylists = playlists->GetSize();
- for(int i=0; i<numPlaylists; i++)
- {
- SyncPlaylist * playlist = (SyncPlaylist *)playlists->Get(i);
- int plnum = -1;
- bool done = false;
- int l = dev->dev->getPlaylistCount();
- int j;
- for(j=0; j < l; j++)
- {
- wchar_t buf[128] = {0};
- dev->dev->getPlaylistName(j,buf,128);
- if(wcscmp(buf,playlist->info.playlistName)) continue;
- int plen = dev->dev->getPlaylistLength(j);
- if(plen != playlist->info.numItems)
- {
- plnum = j;
- break;
- }
- for(int k=0; k<plen; k++)
- {
- if(playlist->songs[k].song != dev->dev->getPlaylistTrack(j,k))
- {
- plnum = j;
- break;
- }
- }
- if(plnum == -1)
- {
- done = true;
- break;
- }
- }
- if(done) continue;
- if(plnum == -1)
- {
- plnum = dev->CreatePlaylist(playlist->info.playlistName,true);
- if(plnum == -1) continue;
- }
- int plen = dev->dev->getPlaylistLength(plnum);
- while(plen && ((plen % 4) != 1)) dev->dev->removeTrackFromPlaylist(plnum,--plen); // avoid granulation boundarys
- int n=0;
- for(j=0; j<playlist->info.numItems; j++)
- {
- songid_t s = playlist->songs[j].song;
- if(s && (n>=plen || s != dev->dev->getPlaylistTrack(plnum,n)))
- {
- // begin set item code...
- if(n >= plen) while(n >= plen)
- {
- dev->dev->addTrackToPlaylist(plnum,s);
- plen++;
- }
- else
- {
- dev->dev->addTrackToPlaylist(plnum,s);
- dev->dev->playlistSwapItems(plnum,plen,n);
- dev->dev->removeTrackFromPlaylist(plnum,plen);
- }
- // end set item code
- }
- if(s) n++;
- }
- plen = dev->dev->getPlaylistLength(plnum);
- while(plen > n) dev->dev->removeTrackFromPlaylist(plnum,--plen);
- if(_wcsicmp(playlist->info.playlistName,L"Podcasts")==0)
- {
- wchar_t *name=NULL;
- for(int j=playlist->info.numItems-1; j>=0; j--)
- {
- wchar_t *n = getRecordExtendedItem(playlist->songs[j].ice,L"podcastchannel");
- if(!name) name=n;
- if(name && n)
- {
- if(_wcsicmp(name,n))
- {
- dev->dev->extraActions(DEVICE_ADDPODCASTGROUP,plnum,j+1,(intptr_t)name);
- name=n;
- }
- if(j==0) dev->dev->extraActions(DEVICE_ADDPODCASTGROUP,plnum,0,(intptr_t)name);
- }
- }
- dev->dev->extraActions(DEVICE_ADDPODCASTGROUP_FINISH,plnum,0,0);
- }
- }
- dev->DevicePropertiesChanges();
- freeMemory();
- WASABI_API_LNGSTRINGW_BUF(IDS_DONE,statusCaption,sizeof(statusCaption)/sizeof(wchar_t));
- TransfersListUpdateItem(this);
- TransfersListUpdateItem(this, dev);
- }
- };
- static bool shouldSyncPlaylist(wchar_t * name, C_Config * config)
- {
- wchar_t buf[150] = {0};
- StringCchPrintf(buf,150, L"sync-%s",name);
- return config->ReadInt(buf,0) == config->ReadInt(L"plsyncwhitelist",1);
- }
- static int sortfunc_podcastpubdate(const void *elem1, const void *elem2)
- {
- itemRecordW *ar = (itemRecordW *)elem1;
- itemRecordW *br = (itemRecordW *)elem2;
- wchar_t *a = getRecordExtendedItem(ar,L"podcastpubdate");
- wchar_t *b = getRecordExtendedItem(br,L"podcastpubdate");
- if(!a) a = L"0";
- if(!b) b = L"0";
- return _wtoi(b) - _wtoi(a);
- }
- void DeviceView::OnActivityStarted()
- {
- for ( ifc_deviceevent *l_event_handler : event_handlers )
- l_event_handler->ActivityStarted( this, this );
- }
- void DeviceView::OnActivityChanged()
- {
- for ( ifc_deviceevent *l_event_handler : event_handlers )
- l_event_handler->ActivityChanged( this, this );
- }
- void DeviceView::OnActivityFinished()
- {
- for ( ifc_deviceevent *l_event_handler : event_handlers )
- l_event_handler->ActivityFinished( this, this );
- }
- void DeviceView::UpdateActivityState()
- {
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue && FALSE == activityRunning)
- {
- if (0 != txQueue->GetSize())
- {
- activityRunning = TRUE;
- if (FAILED(GetProgress(¤tProgress)))
- currentProgress = 0;
-
- OnActivityStarted();
- }
- }
- else
- {
- if (txQueue && 0 == txQueue->GetSize())
- {
- activityRunning = FALSE;
- OnActivityFinished();
- }
- else
- {
- unsigned int percent;
- if (FAILED(GetProgress(&percent)) ||
- percent != currentProgress)
- {
- currentProgress = percent;
- OnActivityChanged();
- }
- }
- }
- }
- void DeviceView::UpdateSpaceInfo(BOOL updateUsedSpace, BOOL notifyChanges)
- {
- uint64_t total, used;
- unsigned int changes;
- changes = 0;
- total = dev->getDeviceCapacityTotal();
- if (total != totalSpace)
- {
- totalSpace = total;
- changes |= (1 << 0);
- }
- if (FALSE != updateUsedSpace)
- {
- used = dev->getDeviceCapacityAvailable();
- if (used > total)
- used = total;
- used = total - used;
- if (used != usedSpace)
- {
- usedSpace = used;
- changes |= (1 << 1);
- }
- }
- if (0 != changes && FALSE != notifyChanges)
- {
- for ( ifc_deviceevent *l_event_handler : event_handlers )
- {
- if (0 != ((1 << 0) & changes))
- l_event_handler->TotalSpaceChanged(this, totalSpace);
- if (0 != ((1 << 1) & changes))
- l_event_handler->TotalSpaceChanged(this, usedSpace);
- }
- }
- }
- void DeviceView::OnNameChanged(const wchar_t *new_name)
- {
- for ( ifc_deviceevent *l_event_handler : event_handlers )
- l_event_handler->DisplayNameChanged( this, new_name );
- }
- void DeviceView::Sync(bool silent)
- {
- // sync configuration settings....
- bool syncAllLibrary = config->ReadInt(L"syncAllLibrary",1)!=0;
- if (AGAVE_API_STATS)
- {
- wchar_t device_name[128] = {0};
- device_name[0] = 0;
- if(dev->extraActions(DEVICE_GET_MODEL, (intptr_t)device_name, 128, 0) == 1 && device_name[0])
- {
- AGAVE_API_STATS->SetString("pmp", device_name);
- }
- }
- HWND centerWindow = CENTER_OVER_ML_VIEW;
- UpdateActivityState();
- C_ItemList mllist;
- wchar_t * querystring=0;
- itemRecordListW *results = 0;
- if(syncAllLibrary)
- {
- querystring = _wcsdup(config->ReadString(L"SyncQuery",L"type=0"));
- results = (AGAVE_API_MLDB ? AGAVE_API_MLDB->Query(querystring) : NULL);
- if (results)
- for(int i = 0; i < results->Size; i++) mllist.Add(&results->Items[i]);
- }
- // read playlists/views and find out what else needs to be added
- PlaylistSyncCopyInst * sync = NULL;
- C_ItemList filenameMaps;
- C_ItemList *songMaps = new C_ItemList;
- C_ItemList * playlists = new C_ItemList;
- // first collect playlists without metadata
- SyncItemListLoader list;
- list.metaToGet = &filenameMaps;
- list.songMaps = songMaps;
- int playlistsnum = SendMessage(plugin.hwndLibraryParent, WM_ML_IPC, 0, ML_IPC_PLAYLIST_COUNT);
- for(int i=0; i<playlistsnum; i++)
- {
- SyncPlaylist* playlist = (SyncPlaylist*)calloc(sizeof(SyncPlaylist),1);
- playlist->info.size = sizeof(mlPlaylistInfo);
- playlist->info.playlistNum = i;
- SendMessage(plugin.hwndLibraryParent, WM_ML_IPC, (WPARAM)&playlist->info, ML_IPC_PLAYLIST_INFO);
- if(shouldSyncPlaylist(playlist->info.playlistName, config))
- {
- playlists->Add(playlist);
- }
- else
- {
- free(playlist);
- playlist = 0;
- continue;
- }
- //if(playlist->info.numItems <= 1)
- {
- list.pos = list.len = 0;
- playlistManager->Load(playlist->info.filename, &list);
- playlist->info.numItems = list.pos;
- }
- list.pos = 0;
- list.len=playlist->info.numItems;
- list.songs = playlist->songs = (songMapping*)calloc(sizeof(songMapping), list.len);
- playlistManager->Load(playlist->info.filename, &list);
- }
- mapFilesToItemRecords((filenameMap **)filenameMaps.GetAll(), filenameMaps.GetSize(), centerWindow); // get metadata
- // now sync podcasts...
- if (dev->extraActions(DEVICE_SUPPORTS_PODCASTS, 0, 0, 0) == 0)
- {
- int podcasteps = config->ReadInt(L"podcast-sync_episodes",0);
- int podcastsnum = AGAVE_API_PODCASTS ? AGAVE_API_PODCASTS->GetNumPodcasts() : 0;
- if(podcasteps && podcastsnum > 0)
- {
- // if we want to sync podcasts and we have podcasts to sync
- bool all = !!config->ReadInt(L"podcast-sync_all", 1);
- SyncPlaylist * s = (SyncPlaylist *)calloc(sizeof(SyncPlaylist),1);
- lstrcpyn(s->info.playlistName, L"Podcasts", 128); //set the name of the playlist containing our podcasts
- int n = 0, alloc = 512;
- s->songs = (songMapping*)calloc(alloc, sizeof(songMapping));
- for(int i = 0; i < podcastsnum; i++)
- {
- ifc_podcast *podcast = AGAVE_API_PODCASTS->EnumPodcast(i);
- if(podcast)
- {
- wchar_t podcast_name[256] = {0};
- if(podcast->GetTitle(podcast_name, 256) == 0)
- {
- wchar_t buf[300] = {0};
- StringCchPrintf(buf, 300, L"podcast-sync-%s", podcast_name);
- if(podcast_name[0] && (all || config->ReadInt(buf,0))) // if we have a podcast and we want to sync it
- {
- wchar_t query[300] = {0};
- StringCchPrintf(query, 300, L"podcastchannel = \"%s\"", podcast_name);
- itemRecordListW *podcasts = AGAVE_API_MLDB->Query(query);
- if(podcasts)
- {
- qsort(podcasts->Items,podcasts->Size,sizeof(itemRecordW),sortfunc_podcastpubdate); // sort the podcasts into publish date order
- for(int j=0; j<podcasts->Size && (podcasteps == -1 || j < podcasteps); j++)
- {
- // add podcast to playlist
- if(n >= alloc)
- {
- size_t old_alloc = alloc;
- alloc += 512;
- songMapping* new_songs = (songMapping*)realloc(s->songs,sizeof(songMapping) * alloc);
- if (new_songs)
- {
- s->songs = new_songs;
- }
- else
- {
- new_songs = (songMapping*)malloc(sizeof(songMapping) * alloc);
- if (new_songs)
- {
- memcpy(new_songs, s->songs, sizeof(songMapping) * old_alloc);
- free(s->songs);
- s->songs = new_songs;
- }
- else
- {
- alloc = old_alloc;
- continue;
- }
- }
- }
- ZeroMemory(&s->songs[n],sizeof(songMapping));
- s->songs[n].ice = (itemRecordW*)calloc(sizeof(itemRecordW), 1);
- copyRecord(s->songs[n].ice,&podcasts->Items[j]);
- mllist.Add(s->songs[n].ice);
- songMaps->Add(&s->songs[n].pladd);
- n++;
- }
- if(podcasts)
- AGAVE_API_MLDB->FreeRecordList(podcasts);
- }
- }
- }
- }
- }
- s->info.numItems = n;
- if(n)
- playlists->Add(s);
- else
- {
- free(s->songs);
- free(s);
- }
- }
- }
- // now collect playlists with metadata (i.e, smart views)
- // except the new ml_local isn't ready.
- // calloc a new SyncPlaylist, fill in playlist->info.numItems, playlist->info.playlistName and playlist->songs[].ice then add to playlists.
- // add tracks to be sync'd
- for(int i=0; i<filenameMaps.GetSize(); i++)
- {
- filenameMap* f = (filenameMap*)filenameMaps.Get(i);
- if(f->ice)
- mllist.Add(f->ice);
- }
- // prepare sync
- if(playlists->GetSize())
- sync = new PlaylistSyncCopyInst(this, songMaps, playlists);
- else
- {
- delete playlists;
- delete songMaps;
- }
- // work out the tracks to be sent and deleted...
- C_ItemList synclist,dellist;
- ProcessDatabaseDifferences(dev, &mllist, NULL, &synclist, NULL, &dellist);
- if(!synclist.GetSize() && !dellist.GetSize())
- {
- // nothing to do
- if(sync)
- {
- sync->SyncPlaylists();
- delete sync;
- }
- if(!silent)
- {
- wchar_t titleStr[32] = {0};
- MessageBox(plugin.hwndLibraryParent,
- WASABI_API_LNGSTRINGW(IDS_NOTHING_TO_SYNC_UP_TO_DATE),
- WASABI_API_LNGSTRINGW_BUF(IDS_SYNC, titleStr, 32),0);
- }
- }
- else
- {
- // need to sync some tracks
- if(IDOK == SyncDialog_Show(centerWindow, this, &synclist, &dellist, FALSE))
- {
- config->WriteInt(L"syncOnConnect_time",(int)time(NULL));
- if(dellist.GetSize())
- {
- switch(config->ReadInt(L"TrueSync",0))
- {
- case 1: this->DeleteTracks(&dellist, centerWindow); break;
- case 2: this->CopyTracksToHardDrive(&dellist); break;
- }
- }
- int i = 0, l = 0;
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- l = synclist.GetSize();
- txQueue->lock();
- for(i = 0; i < l; i++) if(AddTrackToTransferQueue(this, (itemRecordW*)synclist.Get(i), false) == -1) break;
- if(sync) AddTrackToTransferQueue(sync);
- txQueue->unlock();
- }
- if(i != l)
- {
- wchar_t titleStr[128] = {0};
- MessageBox(plugin.hwndLibraryParent,
- WASABI_API_LNGSTRINGW(IDS_THERE_IS_NOT_ENOUGH_SPACE_ON_THE_DEVICE),
- WASABI_API_LNGSTRINGW_BUF(IDS_NOT_ENOUGH_SPACE, titleStr, ARRAYSIZE(titleStr)),
- MB_OK | MB_ICONWARNING);
- }
- }
- else
- {
- if(sync) delete sync;
- }
- }
- if(syncAllLibrary)
- {
- if(results)
- AGAVE_API_MLDB->FreeRecordList(results);
- free(querystring);
- }
- }
- void DeviceView::CloudSync(bool silent)
- {
- if (AGAVE_API_STATS)
- {
- wchar_t device_name[128] = {0};
- if(dev->extraActions(DEVICE_GET_MODEL, (intptr_t)device_name, 128, 0) == 1 && device_name[0])
- {
- AGAVE_API_STATS->SetString("pmp", device_name);
- }
- }
- UpdateActivityState();
- // work out the tracks to be sent...
- C_ItemList *filenameMaps2 = new C_ItemList, synclist;
- DeviceView * hss = 0, * local = 0;
- if (!cloud_hinst) cloud_hinst = (HINSTANCE)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GET_CLOUD_HINST);
- if (cloud_hinst && cloud_hinst != (HINSTANCE)1)
- {
- winampMediaLibraryPlugin *(*gp)();
- gp = (winampMediaLibraryPlugin * (__cdecl *)(void))GetProcAddress(cloud_hinst, "winampGetMediaLibraryPlugin");
- if (gp)
- {
- winampMediaLibraryPlugin *mlplugin = gp();
- if (mlplugin && (mlplugin->version >= MLHDR_VER_OLD && mlplugin->version <= MLHDR_VER))
- {
- // determine the cloud device and alter the device
- // to be checked with as needed by the action done
- for(int i = 0; i < devices.GetSize(); i++)
- {
- DeviceView * d = (DeviceView *)devices.Get(i);
- if (d->isCloudDevice)
- {
- char name[128] = {0};
- if (d->dev->extraActions(DEVICE_GET_UNIQUE_ID, (intptr_t)name, sizeof(name), 0))
- {
- if (!strcmp(name, "hss"/*HSS_CLIENT*/))
- hss = d;
- else if (!strcmp(name, "local_desktop"))
- local = d;
- }
- }
- }
- if (local && hss && local->dev == dev)
- {
- // just use the local library as the source to compare against
- mlplugin->MessageProc(0x403, /*source*/-1, /*dest*/hss->dev->extraActions(DEVICE_GET_CLOUD_DEVICE_ID,0,0,0), (INT_PTR)filenameMaps2);
- }
- else
- {
- // just use the local library as the source to compare against
- mlplugin->MessageProc(0x403, /*source*/-1, /*dest*/dev->extraActions(DEVICE_GET_CLOUD_DEVICE_ID,0,0,0), (INT_PTR)filenameMaps2);
- }
- }
- }
- }
- synclist = *fileListToItemRecords(filenameMaps2, CENTER_OVER_ML_VIEW);
- nu::qsort(synclist.GetAll(), synclist.GetSize(), sizeof(void*), dev, compareSongs);
- if(!synclist.GetSize())
- {
- if(!silent)
- {
- wchar_t titleStr[32] = {0};
- MessageBox(plugin.hwndLibraryParent,
- WASABI_API_LNGSTRINGW(IDS_NOTHING_TO_SYNC_UP_TO_DATE),
- WASABI_API_LNGSTRINGW_BUF(IDS_SYNC,titleStr,32),0);
- }
- }
- else
- {
- DeviceView * destDevice = (local && hss && local->dev == dev ? hss : this);
- // need to sync some tracks
- if(IDOK == SyncCloudDialog_Show(CENTER_OVER_ML_VIEW, destDevice, &synclist))
- {
- int l = synclist.GetSize();
- cloudTransferQueue.lock();
- int i = 0;
- for (; i < l; i++) if (AddTrackToTransferQueue(destDevice, (itemRecordW*)synclist.Get(i), false) == -1) break;
- cloudTransferQueue.unlock();
- if(i != l)
- {
- wchar_t titleStr[128] = {0};
- MessageBox(plugin.hwndLibraryParent,
- WASABI_API_LNGSTRINGW(IDS_THERE_IS_NOT_ENOUGH_SPACE_ON_THE_DEVICE),
- WASABI_API_LNGSTRINGW_BUF(IDS_NOT_ENOUGH_SPACE, titleStr, ARRAYSIZE(titleStr)),
- MB_OK | MB_ICONWARNING);
- }
- }
- }
- }
- extern itemRecordListW * generateAutoFillList(DeviceView * dev, C_Config * config); // from autofill.cpp
- void DeviceView::Autofill()
- {
- HWND centerWindow;
- centerWindow = CENTER_OVER_ML_VIEW;
- if (AGAVE_API_STATS)
- {
- wchar_t device_name[128] = {0};
- if(dev->extraActions(DEVICE_GET_MODEL, (intptr_t)device_name, 128, 0) == 1 && device_name[0])
- {
- AGAVE_API_STATS->SetString("pmp", device_name);
- }
- }
- UpdateActivityState();
- C_ItemList delList,sendList;
- itemRecordListW * autofillList = generateAutoFillList(this,config);
- ProcessDatabaseDifferences(dev,autofillList,NULL,&sendList,NULL,&delList);
-
- if(IDOK == SyncDialog_Show(centerWindow, this, &sendList, &delList, TRUE))
- {
- config->WriteInt(L"syncOnConnect_time", (int)time(NULL));
- // delete all tracks in delList
- if(IDOK == DeleteTracks(&delList, centerWindow))
- {
- // not aborted
- // send all tracks in sendList
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->lock();
- for(int i = 0; i < sendList.GetSize(); i++) AddTrackToTransferQueue(this, (itemRecordW*)sendList.Get(i), false);
- txQueue->unlock();
- }
- }
- }
- if(autofillList)
- freeRecordList(autofillList);
- }
- extern int serverPort;
- bool DeviceView::PlayTracks(C_ItemList * tracks, int startPlaybackAt, bool enqueue, bool msgIfImpossible, HWND parent)
- {
- if(tracks->GetSize() == 0) return true;
- // direct playback?
- if(dev->playTracks((songid_t*)tracks->GetAll(),tracks->GetSize(),startPlaybackAt,enqueue))
- return true;
- if(serverPort>0 && dev->copyToHardDriveSupported())
- {
- // indirect playback?
- if(!enqueue)
- {
- //clear playlist
- SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_DELETE);
- }
- wchar_t buf[2048] = {0};
- dev->getPlaylistName(0,buf,128);
- AutoUrl device(buf);
- for(int i=0; i<tracks->GetSize(); i++)
- {
- songid_t s = (songid_t)tracks->Get(i);
- //encode fields to url format
- wchar_t metadata[2048] = {0};
- dev->getTrackArtist(s,metadata,2048);
- AutoUrl artist(metadata);
- dev->getTrackAlbum(s,metadata,2048);
- AutoUrl album(metadata);
- dev->getTrackTitle(s,metadata,2048);
- AutoUrl title(metadata);
- // construct URL
- wchar_t ext[10]=L"";
- dev->getTrackExtraInfo(s,L"ext",ext,10);
- char buf[8192] = {0};
- StringCchPrintfA(buf,8192, "http://127.0.0.1:%d/?a=%s&l=%s&t=%s&d=%s%s%s",serverPort,artist,album,title,device,*ext?";.":"",(char*)AutoChar(ext));
- // get title
- AutoWide wideUrl(buf);
- wchar_t buf2[4096] = {0};
- getTitle(dev,s,wideUrl,buf2,4096);
- // enqueue file
- enqueueFileWithMetaStructW ef = { wideUrl, buf2, NULL, dev->getTrackLength( s ) / 1000 };
- SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&ef, IPC_PLAYFILEW);
- }
- if(!enqueue) //play item startPlaybackAt
- {
- SendMessage(plugin.hwndWinampParent,WM_WA_IPC,startPlaybackAt,IPC_SETPLAYLISTPOS);
- SendMessage(plugin.hwndWinampParent,WM_COMMAND,40047,0); //stop
- SendMessage(plugin.hwndWinampParent,WM_COMMAND,40045,0); //play
- }
- return true;
- }
- if(msgIfImpossible)
- {
- wchar_t titleStr[32] = {0};
- MessageBox(parent,WASABI_API_LNGSTRINGW(IDS_DOES_NOT_SUPPORT_DIRECT_PLAYBACK),
- WASABI_API_LNGSTRINGW_BUF(IDS_UNSUPPORTED,titleStr,32),0);
- }
- return false;
- }
- bool DeviceView::PlayPlaylist(int playlistId, bool enqueue, bool msgIfImpossible, HWND parent)
- {
- int l = dev->getPlaylistLength(playlistId);
- C_ItemList tracks;
- for(int j=0; j<l; j++)
- tracks.Add((void*)dev->getPlaylistTrack(playlistId,j));
- return PlayTracks(&tracks, 0, enqueue, msgIfImpossible, parent);
- }
- void DeviceView::CopyTracksToHardDrive(C_ItemList * tracks)
- {
- CopyTracksToHardDrive((songid_t*)tracks->GetAll(),tracks->GetSize());
- }
- static void getReverseCopyFilenameFormat(wchar_t* filepath, wchar_t* format, int len, BOOL * uppercaseext)
- {
- wchar_t m_def_extract_path[MAX_PATH] = L"C:\\My Music";
- wchar_t m_def_filename_fmt[MAX_PATH] = L"<Artist> - <Album>\\## - <Trackartist> - <Title>";
- GetDefaultSaveToFolder(m_def_extract_path);
- bool cdrip = !!global_config->ReadInt(L"extractusecdrip", 1);
- const wchar_t *mlinifile = (const wchar_t*)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETMLINIFILEW);
- wchar_t buf[2048] = {0};
- if(cdrip) GetPrivateProfileString(L"gen_ml_config",L"extractpath",m_def_extract_path,buf,2048,mlinifile);
- else lstrcpyn(buf,global_config->ReadString(L"extractpath",m_def_extract_path),2048);
- lstrcpyn(filepath,buf,len);
- int l = wcslen(filepath);
- if(*(filepath+l-1) != L'\\')
- {
- *(filepath+l) = L'\\';
- *(filepath+l+1)=0;
- l++;
- }
- if(cdrip) GetPrivateProfileString(L"gen_ml_config",L"extractfmt2",m_def_filename_fmt,buf,2048,mlinifile);
- else lstrcpyn(buf,global_config->ReadString(L"extractfmt2",m_def_filename_fmt),2048);
- if(l < len) lstrcpyn(format/*+l*/,buf,len - l);
- if(cdrip) *uppercaseext = GetPrivateProfileInt(L"gen_ml_config",L"extractucext",0,mlinifile);
- else *uppercaseext = global_config->ReadInt(L"extractucext",0);
- }
- void DeviceView::CopyTracksToHardDrive(songid_t * tracks, int numTracks)
- {
- if(!dev->copyToHardDriveSupported()) return;
- BOOL uppercaseext=FALSE;
- wchar_t filepath[MAX_PATH] = {0}, format[2048] = {0};
- getReverseCopyFilenameFormat(filepath,format,2048,&uppercaseext);
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->lock();
- for(int i=0; i<numTracks; i++)
- {
- AddTrackToTransferQueue(new ReverseCopyInst(this,filepath,format,tracks[i],true,!!uppercaseext));
- }
- txQueue->unlock();
- }
- }
- void DeviceView::CopyPlaylistToLibrary(int plnum)
- {
- if(plnum==0) return;
- wchar_t name[128] = {0};
- dev->getPlaylistName(plnum,name,128);
- wchar_t filename[MAX_PATH] = {0};
- wchar_t dir[MAX_PATH] = {0};
- GetTempPath(MAX_PATH,dir);
- GetTempFileName(dir,L"pmppl",0,filename);
- _wunlink(filename);
- {
- wchar_t * ext = wcsrchr(filename,L'.');
- if(ext) *ext=0;
- StringCchCat(filename,MAX_PATH,L".m3u");
- }
- FILE * f = _wfopen(filename,L"wt"); if(f)
- {
- fputws(L"#EXTM3U\n",f);
- fclose(f);
- }
- /*
- mlMakePlaylistV2 a = {sizeof(mlMakePlaylistV2),name,ML_TYPE_FILENAMES,"\0\0",PL_FLAG_SHOW | PL_FLAG_FILL_FILENAME};
- SendMessage(plugin.hwndLibraryParent,WM_ML_IPC,(WPARAM)&a,ML_IPC_PLAYLIST_MAKE);
- */
- wchar_t filepath[MAX_PATH] = {0}, format[2048] = {0};
- BOOL uppercaseext=FALSE;
- getReverseCopyFilenameFormat(filepath,format,2048,&uppercaseext);
- int l = dev->getPlaylistLength(plnum);
- LinkedQueue * txQueue = getTransferQueue(this);
- if (txQueue)
- {
- txQueue->lock();
- for(int i=0; i<l; i++)
- AddTrackToTransferQueue(new ReversePlaylistCopyInst(this,filepath,format,dev->getPlaylistTrack(plnum,i),filename,name,i==l-1,true));
- txQueue->unlock();
- }
- }
- void DeviceView::Unregister()
- {
- for(size_t i=0; i < playlistTreeItems.size(); i++)
- {
- HNAVITEM item = playlistTreeItems[i];
- // TODO: free memory associated with the text for item
- MLNavCtrl_DeleteItem(plugin.hwndLibraryParent, item);
- }
- playlistTreeItems.clear();
- if (videoTreeItem)
- MLNavCtrl_DeleteItem(plugin.hwndLibraryParent, videoTreeItem);
- videoTreeItem=0;
- if (AGAVE_API_DEVICEMANAGER)
- AGAVE_API_DEVICEMANAGER->DeviceUnregister(name);
- if (treeItem)
- MLNavCtrl_DeleteItem(plugin.hwndLibraryParent, treeItem);
- treeItem=0;
- }
|