1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185 |
- #include "P4SDevice.h"
- #include <time.h>
- #include "msWMDM_i.c"
- #include "../nu/AutoWide.h"
- #include "../nu/AutoChar.h"
- #include "../WAT/wa_logger.h"
- #include "MyProgress.h"
- #include "WMDRMDeviceApp_i.c"
- extern C_ItemList devices;
- extern HANDLE killEvent;
- extern CRITICAL_SECTION csTransfers;
- #define plext L"pla"
- BOOL FormatResProtocol(const wchar_t *resourceName, const wchar_t *resourceType, wchar_t *buffer, size_t bufferMax);
- static BYTE* GetMetadataItem(IWMDMStorage4 * store, const WCHAR * name);
- static IWMDMStorage4* GetOrCreateFolder(IWMDMStorage4 * store, wchar_t * name, P4SDevice * dev=NULL, bool album=false, const itemRecordW * item=NULL);
- // from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmdm/htm/wmdm_format_capability.asp
- void FreeFormatCapability(WMDM_FORMAT_CAPABILITY formatCap)
- {
- // Loop through all configurations.
- for (UINT i=0; i < formatCap.nPropConfig; i++)
- {
- // Loop through all descriptions of a configuration and delete
- // the values particular to that description type.
- for (UINT j=0; j < formatCap.pConfigs[i].nPropDesc; j++)
- {
- switch (formatCap.pConfigs[i].pPropDesc[j].ValidValuesForm)
- {
- case WMDM_ENUM_PROP_VALID_VALUES_ENUM:
- for (UINT k=0; k < formatCap.pConfigs[i].pPropDesc[j].ValidValues.EnumeratedValidValues.cEnumValues; k++)
- {
- PropVariantClear (&(formatCap.pConfigs[i].pPropDesc[j].ValidValues.EnumeratedValidValues.pValues[k]));
- }
- CoTaskMemFree(formatCap.pConfigs[i].pPropDesc[j].ValidValues.EnumeratedValidValues.pValues);
- break;
- case WMDM_ENUM_PROP_VALID_VALUES_RANGE:
- PropVariantClear (&(formatCap.pConfigs[i].pPropDesc[j].ValidValues.ValidValuesRange.rangeMin));
- PropVariantClear (&(formatCap.pConfigs[i].pPropDesc[j].ValidValues.ValidValuesRange.rangeMax));
- PropVariantClear (&(formatCap.pConfigs[i].pPropDesc[j].ValidValues.ValidValuesRange.rangeStep));
- break;
- case WMDM_ENUM_PROP_VALID_VALUES_ANY:
- // No dynamically allocated memory for this value.
- default:
- break;
- }
- // Free the memory for the description name.
- CoTaskMemFree(formatCap.pConfigs[i].pPropDesc[j].pwszPropName);
- }
- // Free the memory holding the array of description items for this configuration.
- CoTaskMemFree(formatCap.pConfigs[i].pPropDesc);
- }
- // Free the memory pointing to the array of configurations.
- CoTaskMemFree(formatCap.pConfigs);
- formatCap.nPropConfig = 0;
- }
- static HRESULT GetFormatCaps(WMDM_FORMATCODE formatCode, IWMDMDevice3* pDevice)
- {
- // Get a list of supported configurations for the format.
- WMDM_FORMAT_CAPABILITY formatCapList;
- HRESULT hr = pDevice->GetFormatCapability(formatCode, &formatCapList);
- if (FAILED(hr)) return E_FAIL;
- if (formatCapList.nPropConfig == 0)
- {
- FreeFormatCapability(formatCapList);
- return E_FAIL; // operation succeeded, but format not supported.
- }
- // TODO: Display the format name.
- // Loop through the configurations and examine each one.
- for (UINT iConfig = 0; iConfig < formatCapList.nPropConfig; iConfig++)
- {
- WMDM_PROP_CONFIG formatConfig = formatCapList.pConfigs[iConfig];
- // Preference level for this configuration (lower number means more preferred).
- // TODO: Display the preference level for this format configuration.
- // Loop through all properties for this configuration and get supported
- // values for the property. Values can be a single value, a range,
- // or a list of enumerated values.
- for (UINT iDesc = 0; iDesc < formatConfig.nPropDesc; iDesc++)
- {
- WMDM_PROP_DESC propDesc = formatConfig.pPropDesc[iDesc];
- // TODO: Display the property name.
- // Three ways a value can be represented: any, a range, or a list.
- switch (propDesc.ValidValuesForm)
- {
- case WMDM_ENUM_PROP_VALID_VALUES_ANY:
- // TODO: Display a message indicating that all values are valid.
- break;
- case WMDM_ENUM_PROP_VALID_VALUES_RANGE:
- {
- // List these in the docs as the propvariants set.
- WMDM_PROP_VALUES_RANGE rng =
- propDesc.ValidValues.ValidValuesRange;
- // TODO: Display the min, max, and step values.
- }
- break;
- case WMDM_ENUM_PROP_VALID_VALUES_ENUM:
- {
- // TODO: Display a banner for the list of valid values.
- /*
- WMDM_PROP_VALUES_ENUM list = propDesc.ValidValues.EnumeratedValidValues;
- PROPVARIANT pVal;
- for (UINT iValue = 0; iValue < list.cEnumValues; iValue++)
- {
- pVal = list.pValues[iValue];
- // TODO: Display each valid value.
- PropVariantClear(&pVal);
- PropVariantInit(&pVal);
- }*/
- }
- break;
- default:
- FreeFormatCapability(formatCapList);
- return E_FAIL;
- //break;
- }
- }
- }
- // Now clear the memory used by WMDM_FORMAT_CAPABILITY.
- FreeFormatCapability(formatCapList);
- return hr;
- }
- static __time64_t wmdmDateTimeToUnixTime(_WMDMDATETIME * t) {
- tm m={0};
- m.tm_hour = t->wHour;
- m.tm_min = t->wMinute;
- m.tm_sec = t->wSecond;
- m.tm_mday = t->wDay;
- m.tm_mon = t->wMonth;
- m.tm_year = t->wYear;
- return _mktime64(&m);
- }
- HRESULT getMetadata(IWMDMStorage4 *store2,IWMDMMetaData ** meta, bool noMetadata) {
- const wchar_t ** propnames = (const wchar_t**)calloc(15,sizeof(void*));
- propnames[0] = g_wszWMDMFormatCode;
- propnames[1] = g_wszWMDMTitle;
- propnames[2] = g_wszWMDMAuthor;
- propnames[3] = g_wszWMDMAlbumTitle;
- propnames[4] = g_wszWMDMGenre;
- propnames[5] = g_wszWMDMTrack;
- propnames[6] = g_wszWMDMYear;
- propnames[7] = g_wszWMDMFileSize;
- propnames[8] = g_wszWMDMDuration;
- propnames[9] = g_wszWMDMPlayCount;
- propnames[10] = g_wszWMDMUserRating;
- propnames[11] = g_wszWMDMUserLastPlayTime;
- propnames[12] = g_wszWMDMLastModifiedDate;
- propnames[13] = g_wszWMDMAlbumArtist;
- propnames[14] = g_wszWMDMComposer;
- HRESULT h;
- if(noMetadata) {
- h = store2->GetSpecifiedMetadata(1,(LPCWSTR*)propnames,meta);
- if(h == WMDM_S_NOT_ALL_PROPERTIES_RETRIEVED) h = S_OK;
- if(h != S_OK) { // ugh. Guess that this is an AAC/M4A. Dirty workaround hack!
- if (SUCCEEDED(store2->CreateEmptyMetadataObject(meta))) {
- h = S_OK;
- DWORD type = WMDM_FORMATCODE_UNDEFINEDAUDIO;
- (*meta)->AddItem(WMDM_TYPE_DWORD,g_wszWMDMFormatCode,(BYTE*)&type,sizeof(type));
- }
- }
- } else {
- h = store2->GetSpecifiedMetadata(13,(LPCWSTR*)propnames,meta);
- if(h == WMDM_S_NOT_ALL_PROPERTIES_RETRIEVED) h = S_OK;
- }
- free(propnames);
- return h;
- }
- void P4SDevice::foundSong(IWMDMStorage4 * store, IWMDMMetaData * meta,bool video,int pl,wchar_t * artist, wchar_t * album, IWMDMStorage4 * alb, IWMDMMetaData * albmeta) {
- Playlist * pls = (Playlist *)playlists.Get(pl);
- Song * song = new Song;
- song->video = video;
- song->meta = meta;
- song->modified = false;
- song->storage = store;
- song->artist = artist;
- song->album = album;
- if(alb && albmeta) {
- song->alb = alb;
- song->albmeta = albmeta;
- alb->AddRef();
- albmeta->AddRef();
- }
- if(song->artist) song->artist = _wcsdup(song->artist);
- if(song->album) song->album = _wcsdup(song->album);
- pls->songs.Add(song);
- store->AddRef();
- meta->AddRef();
- if(noMetadata || video) {
- wchar_t buf[2048]=L"";
- getTrackAlbum((songid_t)song,buf,2048);
- if(video) meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumTitle,(BYTE*)L"~",4);
- else {
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumTitle,(BYTE*)buf,wcslen(buf)*2 + 2);
- buf[0]=0;
- getTrackArtist((songid_t)song,buf,2048);
- }
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAuthor,(BYTE*)buf,wcslen(buf)*2 + 2);
- buf[0]=0;
- getTrackTitle((songid_t)song,buf,2048);
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMTitle,(BYTE*)buf,wcslen(buf)*2 + 2);
- int n = getTrackTrackNum((songid_t)song);
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMTrack,(BYTE*)&n,sizeof(DWORD));
- __int64 s = (__int64)getTrackSize((songid_t)song);
- meta->AddItem(WMDM_TYPE_QWORD,g_wszWMDMFileSize,(BYTE*)&s,sizeof(__int64));
- }
- }
- void P4SDevice::foundPlaylist(IWMDMStorage4 * store, IWMDMMetaData * meta) {
- DWORD count = 0;
- IWMDMStorage ** stores;
- wchar_t buf[100] = {0};
- store->GetName(buf,100);
- //OutputDebugString(buf);
- if(store->GetReferences(&count,&stores) == S_OK) {
- if(count > 0) {
- Playlist * pl = new Playlist;
- StringCchCopy(pl->name, ARRAYSIZE(pl->name), buf);
- {wchar_t * ext = wcsrchr(pl->name,L'.'); if(ext) *ext=0;}
- pl->storage = store;
- pl->meta = meta;
- meta->AddRef();
- store->AddRef();
- playlists.Add(pl);
- int num = playlists.GetSize()-1;
- for(unsigned int i=0; i<count; i++) {
- IWMDMStorage4 * song=NULL;
- /*{
- wchar_t buf[100] = {0};
- stores[i]->GetName(buf,100);
- OutputDebugString(buf);
- }*/
- if(stores[i]->QueryInterface(&song) == S_OK) if(song) {
- /*
- Song * s = new Song;
- s->modified=false;
- s->storage=song;
- HRESULT h = getMetadata(song,&s->meta);
- if (SUCCEEDED(h)) pl->songs.Add(s);
- else delete s;
- */
- //pl->songs.Add(song);
- IWMDMMetaData * meta;
- if (SUCCEEDED(getMetadata(song,&meta,noMetadata))) {
- foundSong(song,meta,false,num); meta->Release();
- }
- song->Release();
- }
- stores[i]->Release();
- }
- } else {
- //OutputDebugString(L"ref count zero");
- }
- CoTaskMemFree(stores);
- } else {
- //OutputDebugString(L"can't get playlist refs");
- }
- }
- void P4SDevice::traverseStorage(IWMDMStorage * store, int level, wchar_t * artist, wchar_t * album) {
- if(!store) return;
- IWMDMStorage4 * store2=NULL;
- ULONG num;
- //OutputDebugStringA("1A");
- C_ItemList storages;
- {
- IWMDMEnumStorage * enstore=NULL;
- IWMDMStorage * storeold=NULL;
- HRESULT hr = store->EnumStorage(&enstore);
- while(SUCCEEDED(hr)) {
- if (WaitForSingleObject(killEvent,0) == WAIT_OBJECT_0)
- break;
- hr = enstore->Next(1,&storeold,&num);
- if(SUCCEEDED(hr) && storeold) {
- hr = storeold->QueryInterface(&store2);
- storeold->Release();
- if(SUCCEEDED(hr) && store2) {
- storages.Add(store2);
- }
- else break;
- }
- else break;
- }
- if(enstore) enstore->Release();
- }
- //OutputDebugStringA("2A");
- //while (SUCCEEDED(hr) && enstore) {
- IWMDMStorage4 * alb=NULL;
- IWMDMMetaData * albmeta=NULL;
- for(int i=0; i<storages.GetSize(); i++) {
- wchar_t buf[256]=L"";
- store2 = (IWMDMStorage4*)storages.Get(i);
- store2->GetName(buf,256);
- wchar_t *ext = wcsrchr(buf,L'.');
- if(ext && _wcsicmp(ext,L".alb")==0) {
- alb = store2;
- alb->AddRef();
- alb->GetMetadata(&albmeta);
- break;
- }
- }
- //albfiles.Add(new AlbFile(store2,meta));
- for(int i=0; i<storages.GetSize(); i++) {
- if (WaitForSingleObject(killEvent,0) == WAIT_OBJECT_0)
- break;
- //OutputDebugStringA("1");
- store2 = (IWMDMStorage4*)storages.Get(i);
- if(store2 == alb) continue;
- wchar_t buf[256]=L"";
- //OutputDebugStringA("2");
- store2->GetName(buf,256);
- if(playlistsDir == NULL && _wcsicmp(buf,L"My Playlists")==0) { playlistsDir = store2; store2->AddRef(); }
- if(playlistsDir == NULL && _wcsicmp(buf,L"Playlists")==0) { playlistsDir = store2; store2->AddRef(); }
- DWORD attribs=NULL;
- store2->GetAttributes(&attribs,NULL);
- //OutputDebugStringA("3");
- if(attribs & WMDM_FILE_ATTR_FOLDER) {
- if(level==0) artist=buf;
- else if(level==1) album=buf;
- //OutputDebugStringA("5");
- WMDM_STORAGE_ENUM_MODE mode = ENUM_MODE_RAW;
- store2->SetEnumPreference(&mode,0,NULL);
- traverseStorage(store2,level+1,artist,album);
- } else if(attribs & WMDM_FILE_ATTR_FILE || !attribs) {
- IWMDMMetaData * meta=NULL;
- //OutputDebugStringA("1");
- HRESULT h = getMetadata(store2,&meta,noMetadata);
- //OutputDebugStringA("2");
- //OutputDebugStringA("4");
- /*{
- wchar_t buf2[400] = {0};
- wsprintf(buf2,L"name: %s atr: 0x%x, hr: 0x%x %s",buf,attribs,h,h == E_INVALIDARG?L"POOT":L"");
- OutputDebugString(buf2);
- }*/
- if(meta && h == S_OK) {
- wchar_t * name=NULL;
- WMDM_TAG_DATATYPE type;
- BYTE * value=NULL;
- UINT valuelen;
- if(meta->QueryByName(g_wszWMDMFormatCode,&type,&value,&valuelen) == S_OK && type == WMDM_TYPE_DWORD)
- {
- switch(*(DWORD*)value) { // find out what it is...
- case WMDM_FORMATCODE_ABSTRACTAUDIOVIDEOPLAYLIST:
- case WMDM_FORMATCODE_WPLPLAYLIST:
- case WMDM_FORMATCODE_M3UPLAYLIST:
- case WMDM_FORMATCODE_MPLPLAYLIST:
- case WMDM_FORMATCODE_ASXPLAYLIST:
- case WMDM_FORMATCODE_PLSPLAYLIST:
- foundPlaylist(store2,meta);
- break;
- case WMDM_FORMATCODE_ASF:
- case WMDM_FORMATCODE_AVI:
- case WMDM_FORMATCODE_MPEG:
- case WMDM_FORMATCODE_WMV:
- case WMDM_FORMATCODE_MP2:
- case WMDM_FORMATCODE_3GP:
- case WMDM_FORMATCODE_UNDEFINEDVIDEO:
- foundSong(store2,meta,true);
- break;
- case WMDM_FORMATCODE_UNDEFINED:
- { //ugh. nokiahack.
- wchar_t * ext = wcsrchr(buf,'.');
- if(!ext) break;
- if(!_wcsicmp(ext,L".mp4") || !_wcsicmp(ext,L".m4a")) foundSong(store2,meta,false);
- }
- break;
- case WMDM_FORMATCODE_AIFF:
- case WMDM_FORMATCODE_WAVE:
- case WMDM_FORMATCODE_MP3:
- case WMDM_FORMATCODE_WMA:
- case WMDM_FORMATCODE_OGG:
- case WMDM_FORMATCODE_AAC:
- case WMDM_FORMATCODE_MP4:
- case WMDM_FORMATCODE_AUDIBLE:
- case WMDM_FORMATCODE_FLAC:
- case WMDM_FORMATCODE_UNDEFINEDAUDIO:
- foundSong(store2,meta,false,0,0,0,alb,albmeta);
- break;
- }
- } else {
- wchar_t * ext = wcsrchr(buf,'.');
- if(ext) {
- bool m = noMetadata;
- noMetadata = true;
- if(!_wcsicmp(ext,L".mp3") || !_wcsicmp(ext,L".wma")) foundSong(store2,meta,false,0,artist,album);
- else if(!_wcsicmp(ext,L".wmv") || !_wcsicmp(ext,L".avi")) foundSong(store2,meta,true,0,artist,album);
- else if(!_wcsicmp(ext,L".asx") || !_wcsicmp(ext,L".pla")) foundPlaylist(store2,meta);
- noMetadata = m;
- }
- }
- meta->Release();
- if(name) CoTaskMemFree(name);
- if(value) CoTaskMemFree(value);
- }
- }
- if(store2) store2->Release();
- }
- if(alb) alb->Release();
- if(albmeta) albmeta->Release();
- }
- bool P4SDevice::songsEqual(songid_t a, songid_t b) {
- wchar_t ba[1024] = {0};
- wchar_t bb[1024] = {0};
- getTrackTitle(a,ba,1024);
- getTrackTitle(b,bb,1024);
- if(wcscmp(ba,bb)) return false;
- getTrackAlbum(a,ba,1024);
- getTrackAlbum(b,bb,1024);
- if(wcscmp(ba,bb)) return false;
- getTrackArtist(a,ba,1024);
- getTrackArtist(b,bb,1024);
- if(wcscmp(ba,bb)) return false;
- return true;
- }
- int P4SDevice::songsCmp(songid_t a, songid_t b) {
- int q=0;
- wchar_t ba[1024] = {0};
- wchar_t bb[1024] = {0};
- getTrackTitle(a,ba,1024);
- getTrackTitle(b,bb,1024);
- q=wcscmp(ba,bb); if(q) return q;
- getTrackAlbum(a,ba,1024);
- getTrackAlbum(b,bb,1024);
- q=wcscmp(ba,bb); if(q) return q;
- getTrackArtist(a,ba,1024);
- getTrackArtist(b,bb,1024);
- return wcscmp(ba,bb);
- }
- P4SDevice * sortDev;
- static int song_sortfunc(const void *elem1, const void *elem2) {
- songid_t a = *(songid_t *)elem1;
- songid_t b = *(songid_t *)elem2;
- return sortDev->songsCmp(a,b);
- }
- extern IWMDRMDeviceApp * DRMDeviceApp;
- static songid_t BinaryChopFind(songid_t find,Playlist * mpl, P4SDevice * dev) {
- sortDev = dev;
- songid_t * ret = (songid_t*)bsearch(&find,mpl->songs.GetAll(),mpl->songs.GetSize(),sizeof(songid_t),song_sortfunc);
- return ret?*ret:NULL;
- }
- P4SDevice::P4SDevice(IWMDMDevice3* pIDevice, bool noMetadata) : transcoder(NULL) {
- error=0;
- musicDir = L"Music";
- videoDir = L"Video";
- lastChange=NULL;
- this->noMetadata = noMetadata;
- if(DRMDeviceApp && DRMDeviceApp->SynchronizeLicenses(pIDevice,NULL,0,0) == S_OK)
- {
- //OutputDebugString(L"sync!");
- }
- playlistsDir=NULL;
- transferQueueSize=0;
- Playlist * mpl = new Playlist;
- playlists.Add(mpl);
- WMDevice = pIDevice;
- if (NULL != WMDevice)
- {
- WMDevice->AddRef();
- if (FAILED(WMDevice->GetName(name,100)))
- name[0] = L'\0';
- }
- else
- name[0] = L'\0';
- // give loading indication to the user....
- pmpDeviceLoading load;
- load.dev = this;
- load.UpdateCaption = NULL;
- SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)&load,PMP_IPC_DEVICELOADING);
- if(load.UpdateCaption) {
- wchar_t buf[200]=L"";
- wsprintf(buf,WASABI_API_LNGSTRINGW(IDS_LOADING),name);
- load.UpdateCaption(buf,load.context);
- }
- Load();
- }
- void P4SDevice::Load() {
- Playlist * mpl = (Playlist*)playlists.Get(0);
- HRESULT hr;
- IWMDMEnumStorage * enstore=0;
- IWMDMStorage * store0=0;
- IWMDMStorage4 * store=0;
- hr = WMDevice->EnumStorage(&enstore);
- ULONG num;
- if(!enstore) {delete this; return;}
- hr = enstore->Next(1,&store0,&num);
- if (SUCCEEDED(hr)) hr = store0->QueryInterface(&store);
- if(store0) store0->Release();
- else error=1;
- if(enstore) enstore->Release();
- else error=1;
- if (SUCCEEDED(hr) && !error) {
- wchar_t buf[100] = {0};
- store->GetName(buf,100);
- mpl->storage = store;
- store->AddRef();
- WMDM_STORAGE_ENUM_MODE mode = ENUM_MODE_RAW;
- store->SetEnumPreference(&mode,0,NULL);
- //traverseStorage(store);
- IWMDMStorage * playlists;
- if(store->GetStorage(L"Playlists",&playlists) == S_FALSE) {
- if(store->GetStorage(L"My Playlists",&playlists) == S_FALSE)
- {
- playlists = NULL;
- }
- }
- if(playlists)
- {
- traverseStorage(playlists);
- playlists->QueryInterface(&playlistsDir);
- playlists->Release();
- }
- IWMDMStorage * songs = NULL;
- if(store->GetStorage(L"Music",&songs) == S_OK)
- {
- traverseStorage(songs);
- songs->Release();
- }
- else if(store->GetStorage(L"My Music",&songs) == S_OK)
- {
- traverseStorage(songs);
- songs->Release();
- musicDir = L"My Music";
- }
- else if(store->GetStorage(L"Music Files",&songs) == S_OK)
- {
- traverseStorage(songs);
- songs->Release();
- musicDir = L"Music Files";
- }
- else { // create a music folder
- IWMDMStorageControl3 * storeControl=NULL;
- store->QueryInterface(&storeControl);
- if(storeControl) {
- IWMDMStorage * newdir=NULL;
- IWMDMMetaData * meta=NULL;
- store->CreateEmptyMetadataObject(&meta);
- storeControl->Insert3(WMDM_MODE_BLOCK|WMDM_CONTENT_FOLDER,WMDM_FILE_ATTR_FOLDER,NULL,musicDir,NULL,NULL,meta,NULL,&newdir);
- if(newdir) newdir->Release();
- else error=1;
- if(meta) meta->Release();
- else error=1;
- storeControl->Release();
- } else error=1;
- }
- if(store->GetStorage(L"Video",&songs) == S_OK) { traverseStorage(songs); songs->Release(); supportsVideo=true; }
- if(store->GetStorage(L"TV",&songs) == S_OK) { traverseStorage(songs); songs->Release(); supportsVideo=true; }
- if(!playlists && !songs) traverseStorage(store);
- }
- if(!store) error=1;
- if(error) {delete this; return;}
- if(!playlistsDir) playlistsDir = GetOrCreateFolder(store,L"Playlists");
- if(!playlistsDir) {delete this; return;}//MessageBox(plugin.hwndWinampParent,L"An error has occured whilst trying to initialise the playlists on your device.\nPlaylists will not work correctly.",L"Playlists Error",0);
-
- sortDev = this;
- qsort(mpl->songs.GetAll(),mpl->songs.GetSize(),sizeof(void*),song_sortfunc);
- // Now to recombobulate the playlists (this SUCKS slightly less now)
- for(int i=1; i<playlists.GetSize(); i++) {
- Playlist * pl = (Playlist *)playlists.Get(i);
- int l = pl->songs.GetSize();
- for(int j=0; j<l; j++) {
- songid_t plsong = (songid_t)pl->songs.Get(j);
- songid_t mplsong = BinaryChopFind(plsong,mpl,this);
- if(mplsong) pl->songs.Set(j,(void*)mplsong);
- else { pl->songs.Del(j--); l--; }
- Song * p = (Song *)plsong;
- p->meta->Release();
- p->storage->Release();
- delete p;
- }
- }
- requiresALB=false;
- { // check for .alb support
- WMDM_FORMAT_CAPABILITY formatCapList;
- HRESULT hr = WMDevice->GetFormatCapability(WMDM_FORMATCODE_ABSTRACTAUDIOALBUM, &formatCapList);
- bool size=false,data=false,format=false;
- if(!FAILED(hr)) {
- for(unsigned int i=0; i<formatCapList.nPropConfig; i++) {
- WMDM_PROP_CONFIG formatConfig = formatCapList.pConfigs[i];
- for(unsigned int j=0; j<formatConfig.nPropDesc; j++) {
- if(!formatConfig.pPropDesc[j].pwszPropName) continue;
- if(wcscmp(formatConfig.pPropDesc[j].pwszPropName,g_wszWMDMAlbumCoverSize)==0) size=true;
- else if(wcscmp(formatConfig.pPropDesc[j].pwszPropName,g_wszWMDMAlbumCoverData)==0) data=true;
- else if(wcscmp(formatConfig.pPropDesc[j].pwszPropName,g_wszWMDMAlbumCoverFormat)==0) format=true;
- }
- }
- }
- if(size && data && format) requiresALB=true;
- FreeFormatCapability(formatCapList);
- }
-
- devices.Add(this);
- SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICECONNECTED);
- //transcoder = NULL;
- transcoder = (Transcoder*)SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)this,PMP_IPC_GET_TRANSCODER);
- if(transcoder) {
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MP3,WMDevice)))
- transcoder->AddAcceptableFormat(L"mp3");
- //transcoder->AddAcceptableFormat(L"wav");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_WMA,WMDevice)))
- transcoder->AddAcceptableFormat(L"wma");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_ASF,WMDevice)))
- transcoder->AddAcceptableFormat(L"asf");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_AVI,WMDevice)))
- transcoder->AddAcceptableFormat(L"avi");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_OGG,WMDevice)))
- transcoder->AddAcceptableFormat(L"ogg");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_FLAC,WMDevice)))
- transcoder->AddAcceptableFormat(L"flac");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_AUDIBLE,WMDevice)))
- transcoder->AddAcceptableFormat(L"aa");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MPEG,WMDevice))) {
- transcoder->AddAcceptableFormat(L"mpeg");
- transcoder->AddAcceptableFormat(L"mpg");
- }
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_WMV,WMDevice)))
- transcoder->AddAcceptableFormat(L"wmv");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_3GP,WMDevice)))
- transcoder->AddAcceptableFormat(L"3gp");
- if(SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MP4,WMDevice))) {
- transcoder->AddAcceptableFormat(L"mp4");
- transcoder->AddAcceptableFormat(L"m4a");
- }
- if(noMetadata || SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_AAC,WMDevice))) {
- transcoder->AddAcceptableFormat(L"m4a");
- transcoder->AddAcceptableFormat(L"mp4");
- transcoder->AddAcceptableFormat(L"aac");
- }
- }
- }
- static void commitPlaylist(Playlist * pl) {
- int l = pl->songs.GetSize();
- IWMDMStorage ** newOrder = (IWMDMStorage **)calloc(l, sizeof(IWMDMStorage *));
- for(int j=0; j<l; j++) ((Song *)pl->songs.Get(j))->storage->QueryInterface(&newOrder[j]);
- pl->storage->SetReferences(l, newOrder);
- for(int i=0; i<l; i++) newOrder[i]->Release();
- free(newOrder);
- pl->modified = false;
- }
- P4SDevice::~P4SDevice() {
- SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICEDISCONNECTED);
- if(playlistsDir) playlistsDir->Release();
- for(int i=1; i<playlists.GetSize(); i++) {
- Playlist * pl = (Playlist*)playlists.Get(i);
- if(pl->modified) commitPlaylist(pl);
- pl->storage->Release();
- pl->meta->Release();
- }
- if(playlists.GetSize()) {
- Playlist * pl = (Playlist*)playlists.Get(0);
- pl->storage->Release();
- for(int j=0; j < pl->songs.GetSize(); j++) {
- Song * s = (Song *)pl->songs.Get(j);
- if (s)
- {
- if(s->modified) s->storage->SetMetadata(s->meta);
- s->meta->Release();
- s->storage->Release();
- delete s;
- }
- }
- }
- for(int i=0; i<devices.GetSize(); i++) {
- if(devices.Get(i) == (void*)this) {
- devices.Del(i);
- return;
- }
- }
- WMDevice->Release();
- if(transcoder) SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)transcoder,PMP_IPC_RELEASE_TRANSCODER);
- }
- void P4SDevice::Close()
- {
- delete this;
- }
-
- __int64 P4SDevice::getDeviceCapacityAvailable() {
- static __int64 prev;
- IWMDMStorageGlobals * sg = NULL;
- if(!playlistsDir) return 0;
- playlistsDir->GetStorageGlobals(&sg);
- if(sg) {
- ULARGE_INTEGER s;
- sg->GetTotalFree(&s.LowPart,&s.HighPart);
- sg->Release();
- if(s.LowPart == 0 && s.HighPart == 0) return prev;
- return prev = s.QuadPart;
- }
- return prev;
- }
- __int64 P4SDevice::getDeviceCapacityTotal() {
- static __int64 prev;
- IWMDMStorageGlobals * sg = NULL;
- if(!playlistsDir) return 0;
- playlistsDir->GetStorageGlobals(&sg);
- if(sg) {
- ULARGE_INTEGER s;
- sg->GetTotalSize(&s.LowPart,&s.HighPart);
- sg->Release();
- if(s.LowPart == 0 && s.HighPart == 0) return prev;
- return prev = s.QuadPart;
- }
- return prev;
- }
- void P4SDevice::deleteTrack(songid_t songid) {
- lastChange=NULL;
- Song * s = (Song*)songid;
- IWMDMStorageControl3 * storeControl=NULL;
- s->storage->QueryInterface(&storeControl);
- if(!storeControl) return;
- for(int i=0; i<playlists.GetSize(); i++) {
- Playlist * pl = (Playlist *)playlists.Get(i);
- int j = pl->songs.GetSize();
- while(j-- > 0) if((Song *)pl->songs.Get(j) == s) { pl->songs.Del(j); pl->modified=true; }
- }
- if(storeControl->Delete(WMDM_MODE_BLOCK,NULL) != S_OK) return;
- s->meta->Release();
- s->storage->Release();
- storeControl->Release();
- delete s;
- }
- void P4SDevice::commitChanges() {
- for(int i=1; i<playlists.GetSize(); i++) {
- Playlist * pl = (Playlist*)playlists.Get(i);
- if(pl->modified) commitPlaylist(pl);
- }
- Playlist * pl = (Playlist*)playlists.Get(0);
- for(int j=0; j < pl->songs.GetSize(); j++) {
- Song * s = (Song *)pl->songs.Get(j);
- if(s->modified) {
- s->storage->SetMetadata(s->meta);
- s->meta->Release();
- s->storage->GetMetadata(&s->meta);
- s->modified = false;
- }
- }
- lastChange=NULL;
- }
- static int fileSizeA(char * filename)
- {
- FILE * fh = fopen(filename,"rb");
- if(!fh) return -1;
- fseek(fh,0,2); //seek to end;
- int l = ftell(fh);
- fclose(fh);
- return l;
- }
- #define MKVALIDFN(x) { wchar_t * n = x; while(n && *n == L'.') *(n++)=L'_'; while(n && *n) { if(*n == L'|' || *n == L'\\' || *n == L'/' || *n == L'?' || *n == L'<' || *n == L'>' || *n == L':' || *n == L'*' || *n == L'"') *n=L'_'; n++; } n = x+wcslen(x)-1; while(n && *n==L'.' && n>=x) *(n--)=0; }
- static IWMDMStorage4* GetOrCreateFolder(IWMDMStorage4 * store, wchar_t * name, P4SDevice * dev, bool album, const itemRecordW * item) {
- if(!name[0]) name=L"Blank";
- MKVALIDFN(name);
- if(!name[0]) name=L"Blank";
- if(!store) return NULL;
- IWMDMEnumStorage * enstore=NULL;
- HRESULT hr = store->EnumStorage(&enstore);
- IWMDMStorage * store0;
- IWMDMStorage4 * store4;
- ULONG num;
- if(!enstore) return NULL;
- enstore->Reset();
- hr = enstore->Next(1,&store0,&num);
- while(hr == S_OK) {
- store4=NULL;
- store0->QueryInterface(&store4);
- store0->Release();
- wchar_t buf[100] = {0};
- store4->GetName(buf,100);
- if(_wcsicmp(buf,name) == 0) {
- return store4;
- }
- store4->Release();
- hr = enstore->Next(1,&store0,&num);
- }
- if(enstore) enstore->Release();
- // we must create it!
- store0=store4=NULL;
- IWMDMStorageControl3 * storeControl=NULL;
- store->QueryInterface(&storeControl);
- if(!storeControl) return NULL;
- IWMDMMetaData * meta;
- store->CreateEmptyMetadataObject(&meta);
- storeControl->Insert3(WMDM_MODE_BLOCK|WMDM_CONTENT_FOLDER,WMDM_FILE_ATTR_FOLDER,NULL,name,NULL,NULL,meta,NULL,&store0);
- meta->Release();
- if(!store0) return NULL;
- store0->QueryInterface(&store4);
- storeControl->Release();
- store0->Release();
- store->Release();
- if(album) {
- wchar_t buffer[MAX_PATH];
- IWMDMStorageControl3 * storeControl;
- wsprintf(buffer,L"%s.alb",name);
- store4->QueryInterface(&storeControl);
- IWMDMStorage * newpl=NULL;
- IWMDMStorage4 * newpl4=NULL;
- IWMDMMetaData * meta=NULL;
- store4->CreateEmptyMetadataObject(&meta);
- if (meta)
- {
- DWORD formatCode = WMDM_FORMATCODE_ABSTRACTAUDIOALBUM;
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMFormatCode,(BYTE*)&formatCode,sizeof(DWORD));
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumTitle,(BYTE*)name,(wcslen(name)*2)+2);
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumArtist,(BYTE*)((wchar_t*)item->albumartist),(wcslen(item->albumartist)*2)+2);
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMTitle,(BYTE*)name,(wcslen(name)*2)+2);
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAuthor,(BYTE*)((wchar_t*)item->artist),(wcslen(item->artist)*2)+2);
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMGenre,(BYTE*)((wchar_t*)item->genre),(wcslen(item->genre)*2)+2);
- storeControl->Insert3(WMDM_MODE_BLOCK | WMDM_CONTENT_FILE,0,NULL,buffer,NULL,NULL,meta,NULL,&newpl);
- storeControl->Release();
- if (newpl)
- {
- newpl->QueryInterface(&newpl4);
- newpl->Release();
- }
- if (newpl4)
- {
- newpl4->SetReferences(0,NULL);
- newpl4->SetMetadata(meta);
- newpl4->Release();
- }
- meta->Release();
- }
- }
- return store4;
- }
- // Disabled for 5.64
- // Fixes issues with exit failures and duplicates on transfer (view issue only) and other memory corruption issues
- /*typedef struct {
- C_ItemList * playlists;
- void * item;
- } addTrackStruct;
- void CALLBACK addTrack(ULONG_PTR dwParam) {
- addTrackStruct * a = (addTrackStruct *) dwParam;
- ((Playlist*)a->playlists->Get(0))->songs.Add(a->item);
- delete a;
- }*/
- static void getTime(__time64_t value, _WMDMDATETIME * time) {
- if(!time) return;
- ZeroMemory(time,sizeof(_WMDMDATETIME));
- struct tm * t = _localtime64(&value);
- if(!t) return;
- time->wYear = t->tm_year;
- time->wMonth = t->tm_mon;
- time->wDay = t->tm_mday;
- time->wHour = t->tm_hour;
- time->wMinute = t->tm_min;
- time->wSecond = t->tm_sec;
- }
- static int atoi_nullok(char * str) {
- if(str) return atoi(str);
- return 0;
- }
- static IWMDMStorage * storefoo;
- #define PHASE_START 1
- #define PHASE_INPROGRESS 2
- #define PHASE_FINISH 3
- #define PHASE_DONE 4
- #define PHASE_ERROR 5
- extern CSecureChannelClient SAC;
- extern int SynchronousProcedureCall(void * p, ULONG_PTR dwParam);
- void P4SDevice::doTransfer(TransferItem * t) {
- static wchar_t buf[256];
- static IWMDMStorage4 * store;
- static IWMDMStorageControl3 * control;
- switch(t->phase) {
- case PHASE_START:
- {
- bool video = false;
- DWORD formatCode=0;
- wchar_t * point = wcsrchr(t->file,L'.');
- if(point) {
- if(_wcsicmp(point,L".wma")==0) formatCode = WMDM_FORMATCODE_WMA;
- else if(_wcsicmp(point,L".wav")==0) formatCode = WMDM_FORMATCODE_WAVE;
- else if(_wcsicmp(point,L".ogg")==0) formatCode = WMDM_FORMATCODE_OGG;
- else if(_wcsicmp(point,L".m4a")==0) formatCode = WMDM_FORMATCODE_MP4;
- else if(_wcsicmp(point,L".aac")==0) formatCode = WMDM_FORMATCODE_AAC;
- else if(_wcsicmp(point,L".aa")==0) formatCode = WMDM_FORMATCODE_AUDIBLE;
- else if(_wcsicmp(point,L".flac")==0 || _wcsicmp(point,L".fla")==0) formatCode = WMDM_FORMATCODE_FLAC;
- else if(_wcsicmp(point,L".asf")==0) { video=true; formatCode = WMDM_FORMATCODE_ASF; }
- else if(_wcsicmp(point,L".avi")==0) { video=true; formatCode = WMDM_FORMATCODE_AVI; }
- else if(_wcsicmp(point,L".mpg")==0) { video=true; formatCode = WMDM_FORMATCODE_MPEG; }
- else if(_wcsicmp(point,L".mpeg")==0) { video=true; formatCode = WMDM_FORMATCODE_MPEG; }
- else if(_wcsicmp(point,L".wmv")==0) { video=true; formatCode = WMDM_FORMATCODE_WMV; }
- else if(_wcsicmp(point,L".m4v")==0) { video=true; formatCode = WMDM_FORMATCODE_MP4; }
- else if(_wcsicmp(point,L".mp2")==0) { video=true; formatCode = WMDM_FORMATCODE_MP2; }
- else if(_wcsicmp(point,L".mp4")==0) {
- wchar_t buf[10]=L"0";
- extendedFileInfoStructW m = {t->file,L"type",buf,10};
- SendMessage(plugin.hwndWinampParent,WM_WA_IPC,(WPARAM)&m,IPC_GET_EXTENDED_FILE_INFOW);
- formatCode = WMDM_FORMATCODE_MP4;
- video = (buf[0]==L'1');
- }
- else formatCode = WMDM_FORMATCODE_MP3; // mp3 or whatever
- }
- t->video = video;
- store = ((Playlist *)playlists.Get(0))->storage;
- store->AddRef();
- if(video) {
- store = GetOrCreateFolder(store,videoDir,this);
- if(_wcsicmp(t->track->artist,L"")) store = GetOrCreateFolder(store,t->track->artist);
- } else {
- store = GetOrCreateFolder(store,musicDir,this);
- if(_wcsicmp(t->track->artist,L"")) store = GetOrCreateFolder(store,t->track->artist);
- else store = GetOrCreateFolder(store,L"No Artist");
- if(_wcsicmp(t->track->album,L"")) store = GetOrCreateFolder(store,t->track->album,this,requiresALB,t->track);
- else store = GetOrCreateFolder(store,L"No Album");
- }
- /*
- DWORD dw;
- do {
- WMDevice->GetStatus(&dw);
- SleepEx(50,true);
- } while(!(dw & WMDM_STATUS_READY));
- */
- if(!store) {
- t->callback(t->callbackContext,WASABI_API_LNGSTRINGW(IDS_COUND_NOT_CREATE_FOLDER));
- *(t->songid)=NULL;
- t->phase=PHASE_ERROR;
- return;
- }
- // create and fill in metadata...
- HRESULT hr;
- hr = store->CreateEmptyMetadataObject(&t->meta);
- if(hr != S_OK) {
- wchar_t buf[100] = {0};
- wsprintf(buf,WASABI_API_LNGSTRINGW(IDS_COULD_NOT_CREATE_METADATA),hr);
- t->callback(t->callbackContext,buf);
- *(t->songid)=NULL;
- t->phase=PHASE_ERROR;
- return;
- }
- t->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMFormatCode,(BYTE*)&formatCode,sizeof(DWORD));
- if(t->track->artist) t->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAuthor,(BYTE*)((wchar_t*)(t->track->artist)),(wcslen(t->track->artist)*2)+2);
- if(t->track->albumartist) t->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumArtist,(BYTE*)((wchar_t*)(t->track->albumartist)),(wcslen(t->track->albumartist)*2)+2);
- if(t->track->composer) t->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMComposer,(BYTE*)((wchar_t*)(t->track->composer)),(wcslen(t->track->composer)*2)+2);
- if(t->track->album) t->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumTitle,(BYTE*)((wchar_t*)(t->track->album)),(wcslen(t->track->album)*2)+2);
- if(t->track->genre) t->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMGenre,(BYTE*)((wchar_t*)(t->track->genre)),(wcslen(t->track->genre)*2)+2);
- if(t->track->title) t->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMTitle,(BYTE*)((wchar_t*)(t->track->title)),(wcslen(t->track->title)*2)+2);
- if(t->track->track> 0) t->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMTrack,(BYTE*)&t->track->track,sizeof(DWORD));
- __int64 len = t->track->length;
- len *= 10000000;
- wchar_t buf2[256] = {0};
- t->meta->AddItem(WMDM_TYPE_QWORD,g_wszWMDMDuration,(BYTE*)&len,sizeof(__int64));
- int fs = fileSizeA(AutoChar(t->file));
- len = fs;
- t->meta->AddItem(WMDM_TYPE_QWORD,g_wszWMDMFileSize,(BYTE*)&len,sizeof(__int64));
- wsprintf(buf2,L"%d",t->track->year);
- if(t->track->year > 0) t->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMYear,(BYTE*)buf2,(wcslen(buf2)*2) + 2);
- int v;
- if (t->track->length)
- {
- v = 8*(fs/t->track->length); //atoi_nullok(getRecordExtendedItem(t->track,"BITRATE")) * 1000;
- t->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMBitrate,(BYTE*)&v,sizeof(DWORD));
- }
- v = t->track->playcount;
- t->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMPlayCount,(BYTE*)&v,sizeof(DWORD));
- v = t->track->rating;
- if(v>=0 && v<=5) t->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMUserRating,(BYTE*)&v,sizeof(DWORD));
- _WMDMDATETIME time1={0}, time2={0};
- getTime(t->track->lastplay,&time1);
- t->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMUserLastPlayTime,(BYTE*)&time1,sizeof(DWORD));
- getTime(t->track->lastupd,&time2);
- t->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMLastModifiedDate,(BYTE*)&time2,sizeof(DWORD));
- control = NULL;
- store->QueryInterface(&control);
- IWMDMStorage * newstore=NULL;
-
- if(video) wsprintf(buf,L"%s%s",(wchar_t*)(t->track->title),(wchar_t*)(wcsrchr(t->track->filename,'.')));
- else wsprintf(buf,L"%02d - %s%s",t->track->track,(wchar_t*)(t->track->title),(wchar_t*)(wcsrchr(t->track->filename,'.')));
-
- if(video) wsprintf(buf,L"%s%s",(wchar_t*)(t->track->title),wcsrchr(t->file,L'.'));
- else wsprintf(buf,L"%02d - %s%s",t->track->track,(wchar_t*)(t->track->title),wcsrchr(t->file,L'.'));
- MKVALIDFN(buf);
- if(!control) {
- t->callback(t->callbackContext,WASABI_API_LNGSTRINGW(IDS_INCOMPATABLE_DEVICE));
- *(t->songid)=NULL;
- t->phase = PHASE_ERROR;
- return;
- }
-
- t->phase = PHASE_INPROGRESS;
- t->progress = new MyProgress(t);
- storefoo = NULL;
- hr = control->Insert3(WMDM_MODE_BLOCK|WMDM_MODE_TRANSFER_PROTECTED|WMDM_CONTENT_FILE|WMDM_STORAGECONTROL_INSERTAFTER,
- WMDM_FILE_ATTR_FILE,
- t->file,
- buf,
- NULL,
- t->progress,
- t->meta,
- NULL,
- &storefoo);
- //OutputDebugString(L"finished insert");
- if (FAILED(hr)) {
- wchar_t buf1[100] = {0};
- wsprintf(buf1,WASABI_API_LNGSTRINGW(IDS_ERROR_IN_INSERT),hr);
- t->callback(t->callbackContext,buf1);
- *(t->songid)=NULL;
- t->phase = PHASE_ERROR;
- return;
- }
- }
- break;
- case PHASE_FINISH:
- //OutputDebugString(L"phase finish start");
- {
- /*
- DWORD dw;
- WMDevice->GetStatus(&dw);
- while(!(dw == WMDM_STATUS_READY)) {
- SleepEx(50,true);
- WMDevice->GetStatus(&dw);
- }
- */
- }
-
- t->progress->Release();
- control->Release();
- if(storefoo) { /*OutputDebugString(L"storefoo");*/ storefoo->Release(); storefoo=NULL; }
- if(store) {
- IWMDMStorage * store0 = NULL;
- store->GetStorage(buf,&store0);
- store->Release();
- if(store0) {
- IWMDMStorage4 * store4 = NULL;
- store0->QueryInterface(&store4);
- if(store4) {
- store4->AddRef();
- store0->Release();
- store4->SetMetadata(t->meta);
- //t->meta->Release();
- Song * song = new Song;
- song->modified=false;
- song->storage = store4;
- song->meta = t->meta;
- song->video = t->video;
- //((Playlist*)playlists.Get(0))->songs.Add(song);
- // Disabled for 5.64
- // Fixes issues with exit failures and duplicates on transfer (view issue only) and other memory corruption issues
- /*
- addTrackStruct * a = new addTrackStruct;
- a->item=song;
- a->playlists = &playlists;
- //PostMessage(plugin.hwndPortablesParent,WM_USER+3,(WPARAM)addTrack,(LPARAM)a);
- SynchronousProcedureCall((void*)addTrack,(ULONG_PTR)a);
- */
- *(t->songid) = (songid_t)song;
- // sort out the album group...
- if(t->track->album && requiresALB) {
- IWMDMStorage * album0=NULL;
- IWMDMStorage * parent=NULL;
- IWMDMStorage4 * parent4=NULL;
- IWMDMStorage4 * album4;
- wchar_t buf[512] = {0};
- wsprintf(buf,L"%s.alb",(wchar_t*)(t->track->album));
- store4->GetParent(&parent);
- if (parent)
- {
- parent->QueryInterface(&parent4);
- parent->Release();
- if (parent4)
- {
- parent4->GetStorage(buf,&album0);
- parent4->Release();
- if(album0) {
- album0->QueryInterface(&album4);
- album0->Release();
- DWORD refc;
- IWMDMStorage ** refs;
- IWMDMStorage ** newrefs;
- album4->GetReferences(&refc,&refs);
- newrefs = (IWMDMStorage **)calloc((refc + 1), sizeof(void*));
- for(DWORD i=0; i<refc; i++) newrefs[i] = refs[i];
- newrefs[refc] = store4;
- refc++;
- album4->SetReferences(refc,newrefs);
- refc--;
- for(DWORD i=0; i<refc; i++) refs[i]->Release();
- free(newrefs);
- CoTaskMemFree(refs);
- song->alb = album4;
- album4->GetMetadata(&song->albmeta);
- //album4->Release();
- int w,h;
- ARGB32 *bits;
- if (AGAVE_API_ALBUMART->GetAlbumArt(t->file, L"cover", &w, &h, &bits) == ALBUMART_SUCCESS)
- {
- setArt((songid_t)song,bits,w,h);
- WASABI_API_MEMMGR->sysFree(bits);
- }
- }
- }
- }
- }
- }
- }
- }
- if(!*t->songid) t->callback(t->callbackContext,WASABI_API_LNGSTRINGW(IDS_UNSPECIFIED_ERROR));
- t->phase = PHASE_DONE;
- //OutputDebugString(L"phase finish finished");
- break;
- }
- }
- int P4SDevice::transferTrackToDevice(const itemRecordW * track,void * callbackContext,void (*callback)(void * callbackContext, wchar_t * status),songid_t * songid,int * killswitch) {
- wchar_t file[2048] = {0};
- StringCchCopy(file, ARRAYSIZE(file), track->filename);
- bool deletefile = false;
- if(transcoder) if(transcoder->ShouldTranscode(file)) {
- wchar_t newfile[MAX_PATH] = {0};
- wchar_t ext[10] = {0};
- transcoder->CanTranscode(file,ext);
- transcoder->GetTempFilePath(ext,newfile);
- if(transcoder->TranscodeFile(file,newfile,killswitch,callback,callbackContext)) return -1;
- StringCchCopy(file, ARRAYSIZE(file), newfile);
- deletefile=true;
- }
- callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_WAITING_FOR_OTHER_TRANSFERS));
- EnterCriticalSection(&csTransfers); // only one transfer at once, globally :(
- callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING));
- TransferItem t;
- t.file = file;
- t.track = track;
- t.callback = callback;
- t.callbackContext = callbackContext;
- t.killswitch = killswitch;
- t.songid = songid;
- t.dev = this;
- t.phase = PHASE_START;
- t.pc = 0;
- *songid = NULL;
- this->doTransfer(&t); // do the transfer
- if(t.phase == PHASE_FINISH) this->doTransfer(&t); // finish it, if needs be.
- int ret = (*songid)?0:-1;
- if(ret==0) callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_DONE));
- trackRemovedFromTransferQueue(track);
- LeaveCriticalSection(&csTransfers);
- if(deletefile) _wunlink(file);
- return ret;
- }
- bool extentionSupported(IWMDMDevice3* WMDevice, wchar_t * ext,bool aac_and_m4a_support, bool video_supported) {
- if(!ext) return false;
- bool supported=false;
- if(!_wcsicmp(ext,L".mp3")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MP3,WMDevice));
- else if(!_wcsicmp(ext,L".wma")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_WMA,WMDevice));
- else if(!_wcsicmp(ext,L".wav")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_WAVE,WMDevice));
- else if(!_wcsicmp(ext,L".aa")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_AUDIBLE,WMDevice));
- else if(!_wcsicmp(ext,L".m4a") || !_wcsicmp(ext,L".aac")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_AAC,WMDevice)) || SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MP4,WMDevice));
- else if(!_wcsicmp(ext,L".ogg")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_OGG,WMDevice));
- else if(!_wcsicmp(ext,L".flac") || !_wcsicmp(ext,L".fla")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_FLAC,WMDevice));
- else if(!_wcsicmp(ext,L".avi")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_AVI,WMDevice));
- else if(!_wcsicmp(ext,L".mpg") || !_wcsicmp(ext,L".mpeg")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MPEG,WMDevice));
- else if(!_wcsicmp(ext,L".asf")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_ASF,WMDevice));
- else if(!_wcsicmp(ext,L".wmv")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_WMV,WMDevice));
- else if(!_wcsicmp(ext,L".mp4")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MP4,WMDevice)) || SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_AAC,WMDevice));
- else if(!_wcsicmp(ext,L".m4v")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MP4,WMDevice));
- else if(!_wcsicmp(ext,L".mp2")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_MP2,WMDevice));
- else if(!_wcsicmp(ext,L".3gp")) supported = SUCCEEDED(GetFormatCaps(WMDM_FORMATCODE_3GP,WMDevice));
- else return false;
- if(!supported) {
- if(!_wcsicmp(ext,L".mp3") || !_wcsicmp(ext,L".wma") || !_wcsicmp(ext,L".wav")) supported=true;
- if(aac_and_m4a_support && (!_wcsicmp(ext,L".m4a") || !_wcsicmp(ext,L".aac"))) supported=true;
- if(video_supported && (!_wcsicmp(ext,L".asf") || !_wcsicmp(ext,L".avi") || !_wcsicmp(ext,L".mpeg") || !_wcsicmp(ext,L".mpg") || !_wcsicmp(ext,L".wmv"))) supported=true;
- }
- return supported;
- }
- /*
- bool extentionSupported(wchar_t * ext,bool aac_and_m4a_support) {
- if(!ext) return false;
- if(_wcsicmp(ext,L".mp3") && _wcsicmp(ext,L".wma") && _wcsicmp(ext,L".wav")
- && (aac_and_m4a_support || (_wcsicmp(ext,L".m4a") && _wcsicmp(ext,L".aac")))
- ) return false;
- return true;
- }
- */
- 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;
- }
- int P4SDevice::trackAddedToTransferQueue(const itemRecordW * track) {
- __int64 l;
- if(transcoder && transcoder->ShouldTranscode(track->filename)) {
- int k = transcoder->CanTranscode(track->filename);
- if(k == -1) return -2;
- if(k == 0) l = (__int64)fileSize(track->filename);
- else l = (__int64)k;
- } else {
- wchar_t * ext = wcsrchr(track->filename,'.');
- if(!extentionSupported(WMDevice,ext,noMetadata,supportsVideo)) return -2; // fucko: assumes all noMetadata devices are nokia (which is true for now)
- l = (__int64)fileSize(track->filename);
- }
- __int64 test = l;
- __int64 avail = getDeviceCapacityAvailable();
- test += transferQueueSize;
- //test += (__int64)3000000;
- if(test > avail) return -1;
- transferQueueSize += l;
- return 0;
- }
- void P4SDevice::trackRemovedFromTransferQueue(const itemRecordW * track) {
- __int64 l = (__int64)fileSize(track->filename);
- if(transcoder && transcoder->ShouldTranscode(track->filename)) {
- int k = transcoder->CanTranscode(track->filename);
- if(k != -1 && k != 0) l = (__int64)k;
- }
- transferQueueSize -= l;
- }
- __int64 P4SDevice::getTrackSizeOnDevice(const itemRecordW * track) {
- if(transcoder && transcoder->ShouldTranscode(track->filename)) {
- int k = transcoder->CanTranscode(track->filename);
- if(k != -1 && k != 0) return k;
- }
- wchar_t * ext = wcsrchr(track->filename,'.');
- if(!extentionSupported(WMDevice,ext,noMetadata,supportsVideo)) return 0; // fucko: assumes all noMetadata devices are nokia (which is true for now)
- return fileSize(track->filename);
- }
- int P4SDevice::getPlaylistCount() {
- return playlists.GetSize();
- }
- static BYTE* GetMetadataItem(IWMDMMetaData *meta, const WCHAR * name) {
- WMDM_TAG_DATATYPE type;
- BYTE * value=NULL;
- UINT len;
- if(!meta) { return (BYTE*)""; } // OutputDebugString(L"no meta");
- if((meta->QueryByName(name,&type,&value,&len)) != S_OK) { return NULL; /*value;*/ } //wchar_t buf[100]; wsprintf(buf,L"meta fail: %x %s",hr,name); OutputDebugString(buf);
- return value;
- }
- static BYTE* GetMetadataItem(Song * song, const WCHAR * name) {
- WMDM_TAG_DATATYPE type;
- BYTE * value=NULL;
- UINT len;
- if(!song || !(song->meta)) { return (BYTE*)""; } // OutputDebugString(L"no meta");
- if((song->meta->QueryByName(name,&type,&value,&len)) != S_OK) { return NULL; /*value;*/ } //wchar_t buf[100]; wsprintf(buf,L"meta fail: %x %s",hr,name); OutputDebugString(buf);
- return value;
- }
- void P4SDevice::getPlaylistName(int playlistnumber, wchar_t * buf, int len)
- {
- if (NULL == buf)
- return;
- if(playlistnumber == 0)
- {
- if (NULL == WMDevice)
- buf[0] = L'\0';
- else
- {
- HRESULT hr;
- hr = WMDevice->GetName(buf, len);
- if (FAILED(hr))
- {
- buf[0] = L'\0';
- }
- }
- }
- else
- {
- StringCchCopy(buf, len, ((Playlist *)playlists.Get(playlistnumber))->name);
- }
- }
- int P4SDevice::getPlaylistLength(int playlistnumber) {
- if(playlistnumber == -1) return 0;
- return ((Playlist*)playlists.Get(playlistnumber))->songs.GetSize();
- }
- songid_t P4SDevice::getPlaylistTrack(int playlistnumber,int songnum) {
- if(playlistnumber == -1) return NULL;
- return (songid_t)((Playlist*)playlists.Get(playlistnumber))->songs.Get(songnum);
- }
- void P4SDevice::setPlaylistName(int playlistnumber, const wchar_t *buf) {
- if(playlistnumber == -1) return;
- IWMDMStorageControl3 * storeControl=NULL;
- Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
- lstrcpyn(pl->name,buf,128);
- pl->storage->QueryInterface(&storeControl);
- pl->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMTitle,(BYTE*)buf,(wcslen(buf)*2)+2);
- pl->storage->SetMetadata(pl->meta);
- wchar_t buffer[256] = {0};
- wsprintf(buffer,L"%s.%s",buf,plext);
- if(storeControl) {
- storeControl->Rename(WMDM_MODE_BLOCK,buffer,NULL);
- storeControl->Release();
- }
- }
- int sortby;
- //Device * sortDev;
- #define SKIP_THE_AND_WHITESPACE(x) { while (!iswalnum(*x) && *x) x++; if (!_wcsnicmp(x,L"the ",4)) x+=4; while (*x == L' ') x++; }
- int STRCMP_NULLOK(const wchar_t *pa, const wchar_t *pb) {
- if (!pa) pa=L"";
- else SKIP_THE_AND_WHITESPACE(pa)
- if (!pb) pb=L"";
- else SKIP_THE_AND_WHITESPACE(pb)
- return lstrcmpi(pa,pb);
- }
- #undef SKIP_THE_AND_WHITESPACE
- static int sortFunc(const void *elem1, const void *elem2)
- {
- int use_by = sortby;
- songid_t a=(songid_t)*(songid_t *)elem1;
- songid_t b=(songid_t)*(songid_t *)elem2;
- #define RETIFNZ(v) if ((v)!=0) return v;
- // this might be too slow, but it'd be nice
- int x;
- for (x = 0; x < 5; x ++)
- {
- if (use_by == SORTBY_TITLE) // title -> artist -> album -> disc -> track
- {
- wchar_t bufa[2048] = {0};
- wchar_t bufb[2048] = {0};
- sortDev->getTrackTitle(a,bufa,2048);
- sortDev->getTrackTitle(b,bufb,2048);
- int v=STRCMP_NULLOK(bufa,bufb);
- RETIFNZ(v)
- use_by=SORTBY_ARTIST;
- }
- else if (use_by == SORTBY_ARTIST) // artist -> album -> disc -> track -> title
- {
- wchar_t bufa[2048] = {0};
- wchar_t bufb[2048] = {0};
- sortDev->getTrackArtist(a,bufa,2048);
- sortDev->getTrackArtist(b,bufb,2048);
- int v=STRCMP_NULLOK(bufa,bufb);
- RETIFNZ(v)
- use_by=SORTBY_ALBUM;
- }
- else if (use_by == SORTBY_ALBUM) // album -> disc -> track -> title -> artist
- {
- wchar_t bufa[2048] = {0};
- wchar_t bufb[2048] = {0};
- sortDev->getTrackAlbum(a,bufa,2048);
- sortDev->getTrackAlbum(b,bufb,2048);
- int v=STRCMP_NULLOK(bufa,bufb);
- RETIFNZ(v)
- use_by=SORTBY_DISCNUM;
- }
- else if (use_by == SORTBY_DISCNUM) // disc -> track -> title -> artist -> album
- {
- int v1=sortDev->getTrackDiscNum(a);
- int v2=sortDev->getTrackDiscNum(b);
- if (v1<0)v1=0;
- if (v2<0)v2=0;
- RETIFNZ(v1-v2)
- use_by=SORTBY_TRACKNUM;
- }
- else if (use_by == SORTBY_TRACKNUM) // track -> title -> artist -> album -> disc
- {
- int v1=sortDev->getTrackTrackNum(a);
- int v2=sortDev->getTrackTrackNum(b);
- if (v1<0)v1=0;
- if (v2<0)v2=0;
- RETIFNZ(v1-v2)
- use_by=SORTBY_TITLE;
- }
- else if (use_by == SORTBY_GENRE) // genre -> artist -> album -> disc -> track
- {
- wchar_t bufa[2048] = {0};
- wchar_t bufb[2048] = {0};
- sortDev->getTrackGenre(a,bufa,2048);
- sortDev->getTrackGenre(b,bufb,2048);
- int v=STRCMP_NULLOK(bufa,bufb);
- RETIFNZ(v)
- use_by=SORTBY_ARTIST;
- }
- else if (use_by == SORTBY_PLAYCOUNT) // size -> artist -> album -> disc -> track
- {
- int v1=sortDev->getTrackPlayCount(a);
- int v2=sortDev->getTrackPlayCount(b);
- if (v1<0)v1=0;
- if (v2<0)v2=0;
- RETIFNZ(v1-v2)
- use_by=SORTBY_ARTIST;
- }
- else if (use_by == SORTBY_RATING) // size -> artist -> album -> disc -> track
- {
- int v1=sortDev->getTrackRating(a);
- int v2=sortDev->getTrackRating(b);
- if (v1<0)v1=0;
- if (v2<0)v2=0;
- RETIFNZ(v1-v2)
- use_by=SORTBY_ARTIST;
- }
- else if (use_by == SORTBY_LASTPLAYED)
- {
- __time64_t la = sortDev->getTrackLastPlayed(a);
- __time64_t lb = sortDev->getTrackLastPlayed(b);
- double t = difftime((time_t)la,(time_t)lb);
- int v = t>0?1:(t<0?-1:0);
- RETIFNZ(v)
- use_by=SORTBY_ARTIST;
- }
- else break; // no sort order?
- }
- return 0;
- }
- void P4SDevice::sortPlaylist(int playlistnumber, int sortBy) {
- if(playlistnumber == -1) return;
- sortby = sortBy;
- sortDev = this;
- Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
- qsort(pl->songs.GetAll(),pl->songs.GetSize(),sizeof(void*),sortFunc);
- pl->modified = true;
- }
- void P4SDevice::playlistSwapItems(int playlistnumber, int posA, int posB) {
- if(playlistnumber == -1) return;
- Playlist * pl = (Playlist*)playlists.Get(playlistnumber);
- if(posA >= pl->songs.GetSize() || posB >= pl->songs.GetSize()) return;
- void * a = pl->songs.Get(posA);
- void * b = pl->songs.Get(posB);
- pl->songs.Set(posA,b);
- pl->songs.Set(posB,a);
- pl->modified=true;
- }
- void P4SDevice::addTrackToPlaylist(int playlistnumber, songid_t songid) {
- if(playlistnumber == -1) return;
- Playlist * pl = (Playlist*)playlists.Get(playlistnumber);
- pl->songs.Add((void*)songid);
- pl->modified=true;
- }
- void P4SDevice::removeTrackFromPlaylist(int playlistnumber, int songnum) {
- if(playlistnumber == -1) return;
- Playlist * pl = (Playlist*)playlists.Get(playlistnumber);
- pl->songs.Del(songnum);
- pl->modified=true;
- }
- void P4SDevice::deletePlaylist(int playlistnumber) {
- if(playlistnumber == -1) return;
- IWMDMStorageControl3 * storeControl;
- Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
- pl->storage->QueryInterface(&storeControl);
- storeControl->Delete(WMDM_MODE_BLOCK,NULL);
- pl->meta->Release();
- pl->storage->Release();
- playlists.Del(playlistnumber);
- storeControl->Release();
- }
- int P4SDevice::newPlaylist(const wchar_t *name) {
- IWMDMStorageControl3 * storeControl;
- if(!playlistsDir) return -1;
- playlistsDir->QueryInterface(&storeControl);
- DWORD dw=WMDM_FORMATCODE_ABSTRACTAUDIOVIDEOPLAYLIST;
- IWMDMMetaData* meta = NULL;
- int ret = -1;
- if (SUCCEEDED(playlistsDir->CreateEmptyMetadataObject(&meta)) && meta)
- {
- meta->AddItem(WMDM_TYPE_DWORD, g_wszWMDMFormatCode, (BYTE *)&dw, sizeof(dw));
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMTitle,(BYTE*)name,(wcslen(name)*2)+2);
- IWMDMStorage * newpl=NULL;
- wchar_t buffer[MAX_PATH] = {0};
- wsprintf(buffer,L"%s.%s",name,plext);
- storeControl->Insert3(WMDM_MODE_BLOCK | WMDM_CONTENT_FILE,0,NULL,buffer,NULL,NULL,meta,NULL,&newpl);
- if(newpl) {
- IWMDMStorage4 * newpl4=NULL;
- newpl->QueryInterface(&newpl4);
- Playlist * pl = new Playlist;
- lstrcpyn(pl->name,name,128);
- pl->storage = newpl4;
- pl->modified = false;
- pl->meta = meta;
- playlists.Add(pl);
- ret = playlists.GetSize() - 1;
- newpl->Release();
- }
- }
- storeControl->Release();
- return ret;
- }
- void P4SDevice::getTrackArtist(songid_t songid, wchar_t * buf, int len) {
- buf[0]=0;
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMAuthor);
- if(b) { lstrcpyn(buf,(wchar_t*)b,len); CoTaskMemFree(b); }
- if(noMetadata || !b) {
- if(!buf[0]) { // guess based upon file path
- Song *s = (Song *)songid;
- if(s->artist) {lstrcpyn(buf,s->artist,len);
- return;
- }
- IWMDMStorage * p = NULL;
- if(s->storage->GetParent(&p) == S_OK) {
- IWMDMStorage * p2 = NULL;
- IWMDMStorage4 * p3 = NULL;
- if (SUCCEEDED(p->QueryInterface(&p3))) {
- if(p3->GetParent(&p2) == S_OK) {
- p2->GetName(buf,len);
- p2->Release();
- }
- p3->Release();
- }
- p->Release();
- }
- }
- }
- }
- void P4SDevice::getTrackAlbum(songid_t songid, wchar_t * buf, int len) {
- buf[0]=0;
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMAlbumTitle);
- if(b) { lstrcpyn(buf,(wchar_t*)b,len); CoTaskMemFree(b); }
- if(!b || noMetadata || ((Song*)songid)->video) {
- if(!buf[0]) { // guess based upon file path
- Song *s = (Song *)songid;
- if(s->album) {lstrcpyn(buf,s->album,len); return;}
- IWMDMStorage * p = NULL;
- if(s->storage->GetParent(&p) == S_OK) {
- p->GetName(buf,len);
- p->Release();
- }
- }
- }
- if(buf[0] == L'~' && buf[1] == 0) buf[0]=0;
- }
- void P4SDevice::getTrackTitle(songid_t songid, wchar_t * buf, int len) {
- buf[0]=0;
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMTitle);
- if(b) { lstrcpyn(buf,(wchar_t*)b,len); CoTaskMemFree(b); }
- if(!b || noMetadata || ((Song*)songid)->video) {
- if(!buf[0]) { // guess based upon file name
- Song *s = (Song *)songid;
- wchar_t buf2[256]=L"";
- s->storage->GetName(buf2,256);
- wchar_t * n = wcsrchr(buf2,L'-');
- if(n) {
- while(n && (*n == L'-' || *n == L' ' || *n == L'_' || *n == L'.')) n++;
- lstrcpyn(buf,n,len);
- } else lstrcpyn(buf,buf2,len);
- }
- wchar_t * ext = wcsrchr(buf,L'.');
- if(ext) *ext=0;
- }
- }
- void P4SDevice::getTrackGenre(songid_t songid, wchar_t * buf, int len) {
- buf[0]=0;
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMGenre);
- if(b) { lstrcpyn(buf,(wchar_t*)b,len); CoTaskMemFree(b); }
- }
- int P4SDevice::getTrackTrackNum(songid_t songid) {
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMTrack);
- int r = b?(int)*((DWORD*)b):0; if(b) CoTaskMemFree(b);
- if(r) return r;
- if(!b || noMetadata) { // guess based upon file name
- Song *s = (Song *)songid;
- wchar_t buf2[256]=L"";
- s->storage->GetName(buf2,256);
- wchar_t * n = buf2; //wcschr(buf2,L'-');
- while(n) {
- while((*n == L'-' || *n == L' ' || *n == L'_' || *n == L'.') && *n) n++;
- if(!n) break;
- int m=0; while(*(n+m)>=L'0' && *(n+m)<=L'9') m++;
- if(m == 2) { *(n+m)=0; return _wtoi(n); }
- n = wcschr(n,L'-');
- }
- /*
- wchar_t * n = wcschr(buf2,L'-');
- if(n) {
- *(n--)=0;
- while((*n == L'-' || *n == L' ' || *n == L'_' || *n == L'.') && n > buf2) *(n--)=0;
- return _wtoi(buf2);
- }
- */
- }
- return 0;
- }
- int P4SDevice::getTrackYear(songid_t songid) {
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMYear);
- int r = b?_wtoi((wchar_t*)b):0; if(b) CoTaskMemFree(b); return r;
- }
- __int64 P4SDevice::getTrackSize(songid_t songid) {
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMFileSize);
- int r = b?(int)*((__int64*)b):0; if(b) CoTaskMemFree(b);
- if(r) return r;
- DWORD high, low;
- ((Song *)songid)->storage->GetSize(&low,&high);
- ULARGE_INTEGER u;
- u.HighPart = high;
- u.LowPart = low;
- return u.QuadPart;
- }
- int P4SDevice::getTrackLength(songid_t songid) {
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMDuration);
- int r = b?(int)(*((__int64*)b)/10000):0; if(b) CoTaskMemFree(b); return r;
- }
- int P4SDevice::getTrackBitrate(songid_t songid) {
- int len = getTrackLength(songid) / 8000;
- return len?(int)(getTrackSize(songid)/1024) / len:0;
- }
- int P4SDevice::getTrackPlayCount(songid_t songid) {
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMPlayCount);
- int r = b?(int)*((DWORD*)b):0; if(b) CoTaskMemFree(b); return r;
- }
- int P4SDevice::getTrackRating(songid_t songid) {
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMUserRating);
- int r = b?(int)*((DWORD*)b):0; if(b) CoTaskMemFree(b); return r;
- }
- __time64_t P4SDevice::getTrackLastPlayed(songid_t songid) {
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMUserLastPlayTime);
- __time64_t r = b?wmdmDateTimeToUnixTime((_WMDMDATETIME *)b):0; if(b) CoTaskMemFree(b); return r;
- }
- __time64_t P4SDevice::getTrackLastUpdated(songid_t songid) {
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMLastModifiedDate);
- __time64_t r = b?wmdmDateTimeToUnixTime((_WMDMDATETIME *)b):0; if(b) CoTaskMemFree(b); return r;
- }
- void P4SDevice::getTrackAlbumArtist(songid_t songid, wchar_t * buf, int len) {
- buf[0]=0;
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMAlbumArtist);
- if(b) { lstrcpyn(buf,(wchar_t*)b,len); CoTaskMemFree(b); }
- if(!buf[0]) getTrackArtist(songid,buf,len);
- }
- void P4SDevice::getTrackComposer(songid_t songid, wchar_t * buf, int len) {
- buf[0]=0;
- BYTE * b = GetMetadataItem((Song *)songid,g_wszWMDMComposer);
- if(b) { lstrcpyn(buf,(wchar_t*)b,len); CoTaskMemFree(b); }
- }
- int P4SDevice::getTrackType(songid_t songid) {
- Song * s = (Song *)songid;
- return s->video;
- }
- void P4SDevice::getTrackExtraInfo(songid_t songid, const wchar_t * field, wchar_t * buf, int len) {
- if(!wcscmp(field,FIELD_EXTENSION)) {
- Song * s = (Song *)songid;
- wchar_t buf2[2048] = {0};
- s->storage->GetName(buf2,2048);
- wchar_t * ext = wcsrchr(buf2,L'.');
- if(ext) { ext++; lstrcpyn(buf,ext,len); }
- }
- }
- void P4SDevice::PreCommit(Song * s) {
- if(!lastChange) lastChange = s;
- else if(s != lastChange) {
- if(lastChange->modified) {
- lastChange->storage->SetMetadata(lastChange->meta);
- lastChange->meta->Release();
- lastChange->storage->GetMetadata(&lastChange->meta);
- lastChange->modified = false;
- }
- lastChange = s;
- }
- }
- void P4SDevice::setTrackArtist(songid_t songid, const wchar_t * value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAuthor,(BYTE*)value,wcslen(value)*2+2);
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackAlbum(songid_t songid, const wchar_t * value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumTitle,(BYTE*)value,wcslen(value)*2+2);
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackTitle(songid_t songid, const wchar_t * value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMTitle,(BYTE*)value,wcslen(value)*2+2);
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackGenre(songid_t songid, const wchar_t * value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMGenre,(BYTE*)value,wcslen(value)*2+2);
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackTrackNum(songid_t songid, int value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMTrack,(BYTE*)&value,sizeof(DWORD));
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackYear(songid_t songid, int value) {
- wchar_t buf[10] = {0}; wsprintf(buf,L"%d",value);
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMYear,(BYTE*)buf,wcslen(buf)*2+2);
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackPlayCount(songid_t songid, int value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMPlayCount,(BYTE*)&value,sizeof(DWORD));
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackRating(songid_t songid, int value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMUserRating,(BYTE*)&value,sizeof(DWORD));
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackLastPlayed(songid_t songid, __time64_t value) {
- _WMDMDATETIME time={0};
- getTime(value,&time);
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_DATE,g_wszWMDMUserLastPlayTime,(BYTE*)&time,sizeof(_WMDMDATETIME));
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackLastUpdated(songid_t songid, __time64_t value) {
- _WMDMDATETIME time={0};
- getTime(value,&time);
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_DATE,g_wszWMDMLastModifiedDate,(BYTE*)&time,sizeof(_WMDMDATETIME));
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackAlbumArtist(songid_t songid, const wchar_t * value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumArtist,(BYTE*)value,wcslen(value)*2+2);
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- void P4SDevice::setTrackComposer(songid_t songid, const wchar_t * value) {
- ((Song*)songid)->meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMComposer,(BYTE*)value,wcslen(value)*2+2);
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- }
- int P4SDevice::copyToHardDrive(songid_t s,wchar_t * path,void * callbackContext,void (*callback)(void * callbackContext, wchar_t * status),int * killswitch)
- {
- callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_WAITING));
- EnterCriticalSection(&csTransfers);
- Song * song = (Song*)s;
- IWMDMStorageControl * control;
- if (!SUCCEEDED(song->storage->QueryInterface(&control))) {
- callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_FAILED));
- return -1;
- }
- wchar_t fn[2084] = {0};
- wchar_t *ext = 0;
- if(SUCCEEDED(song->storage->GetName(fn,2084)) && (ext=wcsrchr(fn,L'.'))!=0)
- wcscat(path,ext);
- int ret=-1;
- callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING));
- TransferItem t={0};
- t.callback = callback;
- t.callbackContext = callbackContext;
- t.killswitch = killswitch;
- t.progress = new MyProgress(&t);
- if(SUCCEEDED(control->Read(WMDM_MODE_BLOCK | WMDM_CONTENT_FILE,path,t.progress,NULL))) ret=0;
- control->Release();
- t.progress->Release();
- callback(callbackContext,WASABI_API_LNGSTRINGW((ret==0?IDS_DONE:IDS_FAILED)));
- LeaveCriticalSection(&csTransfers);
- return ret;
- }
- static IWMDMStorage4* getAlb(P4SDevice * dev, songid_t songid, bool create) {
- wchar_t alb[1024] = {0};
- dev->getTrackAlbum(songid,alb,1020);
- StringCchCat(alb, ARRAYSIZE(alb), L".alb");
- Song * song = (Song*)songid;
- IWMDMStorage * album0=NULL;
- IWMDMStorage * parent=NULL;
- IWMDMStorage4 * parent4=NULL;
- IWMDMStorage4 * album4=NULL;
- song->storage->GetParent(&parent);
- if (parent)
- {
- parent->QueryInterface(&parent4);
- parent->Release();
- if (parent4)
- {
- parent4->GetStorage(alb,&album0);
- //parent4->Release();
- if(album0) {
- album0->QueryInterface(&album4);
- album0->Release();
- }
- }
- }
- if(album4 || !create) { parent4->Release(); return album4; }
- if(!parent4) return NULL;
- // create my own
- album0=0;
- IWMDMStorageControl3 * storeControl=0;
- parent4->QueryInterface(&storeControl);
- if(storeControl) {
- IWMDMMetaData * meta=0;
- parent4->CreateEmptyMetadataObject(&meta);
- if(meta) {
- DWORD formatCode = WMDM_FORMATCODE_ABSTRACTAUDIOALBUM;
- wchar_t album[256]=L"";
- wchar_t artist[256]=L"";
- wchar_t genre[256]=L"";
- dev->getTrackAlbumArtist(songid,artist,256);
- dev->getTrackAlbum(songid,album,256);
- dev->getTrackGenre(songid,genre,256);
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMFormatCode,(BYTE*)&formatCode,sizeof(DWORD));
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumTitle,(BYTE*)album,(wcslen(album)*2)+2);
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMAlbumArtist,(BYTE*)artist,(wcslen(artist)*2)+2);
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMTitle,(BYTE*)album,(wcslen(album)*2)+2);
- meta->AddItem(WMDM_TYPE_STRING,g_wszWMDMGenre,(BYTE*)genre,(wcslen(genre)*2)+2);
- storeControl->Insert3(WMDM_MODE_BLOCK | WMDM_CONTENT_FILE,0,NULL,alb,NULL,NULL,meta,NULL,&album0);
- meta->Release();
- }
- storeControl->Release();
- }
- parent4->Release();
- if(album0) {
- album0->QueryInterface(&album4);
- album0->Release();
- return album4;
- }
- return NULL;
- }
- void P4SDevice::setArt(songid_t songid, void *buf, int w, int h) { //buf is in format ARGB32*
- if(!songid) return;
- Song * s = (Song *)songid;
- IWMDMStorage4 * album = s->alb;
- if(!album) {
- album = getAlb(this,songid,true);
- if(!album) return;
- s->alb = album;
- s->albmeta = NULL;
- s->alb->GetMetadata(&s->albmeta);
- if(!s->albmeta) return;
- }
- IWMDMMetaData *meta=s->albmeta;
- if(!meta) return;
- IWMDMMetaData *meta2 = ((Song*)songid)->meta;
- if(meta || meta2) {
- if(buf) {
- SkinBitmap art((ARGB32*)buf,w,h);
- w=h=120;
- BltCanvas artc(w,h);
- art.stretch(&artc,0,0,w,h);
- const GUID JPEGwriteguid = { 0x7bc27468, 0x475, 0x4c0d, { 0xae, 0xed, 0xc, 0x51, 0x19, 0x5d, 0xc2, 0xea } };
- svc_imageWriter* jpgWrite=NULL;
- waServiceFactory *sf = plugin.service->service_getServiceByGuid(JPEGwriteguid);
- if(sf) jpgWrite = (svc_imageWriter*)sf->getInterface();
- if(jpgWrite) {
- int length=0;
- void *jpeg = jpgWrite->convert(artc.getBits(),32,w,h,&length);
- if(jpeg) {
- DWORD fmt = WMDM_FORMATCODE_IMAGE_EXIF; // this is the formatcode for jpeg, apparently.
- if(meta) {
- meta->AddItem(WMDM_TYPE_BINARY,g_wszWMDMAlbumCoverData,(BYTE*)jpeg,length);
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverWidth,(BYTE*)&w,sizeof(DWORD));
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverHeight,(BYTE*)&h,sizeof(DWORD));
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverSize,(BYTE*)&length,sizeof(DWORD));
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverFormat,(BYTE*)&fmt,sizeof(DWORD));
- }
- if(meta2) {
- meta2->AddItem(WMDM_TYPE_BINARY,g_wszWMDMAlbumCoverData,(BYTE*)jpeg,length);
- meta2->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverWidth,(BYTE*)&w,sizeof(DWORD));
- meta2->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverHeight,(BYTE*)&h,sizeof(DWORD));
- meta2->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverSize,(BYTE*)&length,sizeof(DWORD));
- meta2->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverFormat,(BYTE*)&fmt,sizeof(DWORD));
- }
- WASABI_API_MEMMGR->sysFree(jpeg);
- }
- if (sf) sf->releaseInterface(jpgWrite);
- }
- } else { // remove art
- if(meta) {
- meta->AddItem(WMDM_TYPE_BINARY,g_wszWMDMAlbumCoverData,(BYTE*)0,0);
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverWidth,(BYTE*)0,0);
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverHeight,(BYTE*)0,0);
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverSize,(BYTE*)0,0);
- meta->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverFormat,(BYTE*)0,0);
- }
- if(meta2) {
- meta2->AddItem(WMDM_TYPE_BINARY,g_wszWMDMAlbumCoverData,(BYTE*)0,0);
- meta2->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverWidth,(BYTE*)0,0);
- meta2->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverHeight,(BYTE*)0,0);
- meta2->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverSize,(BYTE*)0,0);
- meta2->AddItem(WMDM_TYPE_DWORD,g_wszWMDMAlbumCoverFormat,(BYTE*)0,0);
- }
- }
- if(meta) {
- album->SetMetadata(meta);
- }
- }
- ((Song*)songid)->modified=true;
- PreCommit((Song*)songid);
- /*
- g_wszWMDMAlbumCoverData Album art JPEG byte blob WMDM_TYPE_BINARY BYTE*
- g_wszWMDMAlbumCoverDuration Album cover duration WMDM_TYPE_DWORD DWORD
- g_wszWMDMAlbumCoverFormat Album art format WMDM_TYPE_DWORD DWORD
- g_wszWMDMAlbumCoverHeight Album art height WMDM_TYPE_DWORD DWORD
- g_wszWMDMAlbumCoverSize Album art size WMDM_TYPE_DWORD DWORD
- g_wszWMDMAlbumCoverWidth Album art width WMDM_TYPE_DWORD DWORD
- */
- }
- class Art {
- public:
- Art(void * jpegData, int jpegDataLen, int w, int h) : jpegData(jpegData), jpegDataLen(jpegDataLen), w(w), h(h), data(0), resized(0) {
- }
- ~Art() {
- CoTaskMemFree(jpegData);
- if(data) WASABI_API_MEMMGR->sysFree(data); data=0;
- }
- ARGB32 * GetImage() {
- if(data) return data;
- const GUID JPEGguid = { 0xae04fb30, 0x53f5, 0x4032, { 0xbd, 0x29, 0x3, 0x2b, 0x87, 0xec, 0x34, 0x04 } };
- svc_imageLoader* jpgLoad=NULL;
- waServiceFactory *sf = plugin.service->service_getServiceByGuid(JPEGguid);
- if(sf) jpgLoad = (svc_imageLoader*)sf->getInterface();
- if(jpgLoad) {
- data = jpgLoad->loadImage(jpegData,jpegDataLen,&w,&h);
- if (sf) sf->releaseInterface(jpgLoad);
- }
- resized=0;
- return data;
- }
- int resized;
- void Resize(int width, int height) {
- if(w == width && h == height) return;
- if(resized) {
- if(data) WASABI_API_MEMMGR->sysFree(data);
- data=0;
- resized=0;
- }
- GetImage();
- if(!data) return;
- SkinBitmap temp(data,w,h);
- BltCanvas newImage(width,height);
- temp.stretch(&newImage,0,0,width,height);
- w=width;
- h=height;
- WASABI_API_MEMMGR->sysFree(data);
- data = (ARGB32*)WASABI_API_MEMMGR->sysMalloc(w*h*sizeof(ARGB32));
- memcpy(data,newImage.getBits(),w*h*sizeof(ARGB32));
- resized=1;
- }
- int getWidth() {return w;}
- int getHeight() {return h;}
- int cmp(Art * art) {
- if(art->jpegDataLen != jpegDataLen) return art->jpegDataLen - jpegDataLen;
- return memcmp(art->jpegData,jpegData,jpegDataLen);
- }
- protected:
- void * jpegData;
- int jpegDataLen;
- int w,h;
- ARGB32 *data;
- };
- pmpart_t P4SDevice::getArt(songid_t songid) {
- if(!songid) return NULL;
- Song* s = (Song*)songid;
- WMDM_TAG_DATATYPE type;
- BYTE * data=NULL;
- UINT length=0;
- IWMDMMetaData *meta = s->albmeta;
- if(!meta) return NULL;
- HRESULT hr = meta->QueryByName(g_wszWMDMAlbumCoverData,&type,&data,&length);
- if(hr == S_OK && data && length) {
- BYTE * b = GetMetadataItem(meta,g_wszWMDMAlbumCoverWidth);
- int w = b?(int)*((DWORD*)b):0;
- if(b) CoTaskMemFree(b);
- b = GetMetadataItem(meta,g_wszWMDMAlbumCoverHeight);
- int h = b?(int)*((DWORD*)b):0;
- if(b) CoTaskMemFree(b);
- //meta->Release();
- if(!w) w=120; // this happens if the device doesn't store the w and h of the image.
- if(!h) h=120; // but it's ok, cause the real values are in the jpeg data, and these can just be a guide.
- return (pmpart_t) new Art(data,length,w,h);
- }
- //meta->Release();
- if(data) CoTaskMemFree(data);
- return NULL;
- }
- void P4SDevice::releaseArt(pmpart_t art) {
- if(art) delete ((Art *)art);
- }
- int P4SDevice::drawArt(pmpart_t art0, HDC dc, int x, int y, int w, int h) {
- Art* art = (Art*)art0;
- if(!art) return 0;
- ARGB32 * d = art->GetImage();
- if(!d) return 0;
- SkinBitmap(d, art->getWidth(), art->getHeight()).stretch(&DCCanvas(dc),x,y,w,h); // wrap into a SkinBitmap (no copying involved)
- return 1;
- }
- void P4SDevice::getArtNaturalSize(pmpart_t art0, int *w, int *h) {
- Art* art = (Art*)art0;
- *w=art->getWidth();
- *h=art->getWidth();
- if(*w==0 || *h==0) *w=*h=120;
- }
- void P4SDevice::setArtNaturalSize(pmpart_t art0, int w, int h) {
- Art* art = (Art*)art0;
- art->Resize(w,h);
- }
- void P4SDevice::getArtData(pmpart_t art0, void* data) { // data ARGB32* is at natural size
- Art* art = (Art*)art0;
- int w,h;
- getArtNaturalSize(art0,&w,&h);
- setArtNaturalSize(art0,w,h);
- ARGB32 * d = art->GetImage();
- if(d) memcpy(data,d,w*h*sizeof(ARGB32));
- }
- bool P4SDevice::artIsEqual(pmpart_t a, pmpart_t b) {
- if(!a || !b) return false;
- return ((Art*)a)->cmp((Art*)b) == 0;
- }
- extern void checkForDevices();
- intptr_t P4SDevice::extraActions(intptr_t param1, intptr_t param2, intptr_t param3,intptr_t param4) {
- switch(param1) {
- case DEVICE_SET_ICON: // icons
- {
- MLTREEIMAGE * i = (MLTREEIMAGE*)param2;
- if(wcsstr(name,L"Zen")) {
- i->hinst = plugin.hDllInstance;
- i->resourceId = IDR_CREATIVE_ZEN_ICON;
- } else if (wcsstr(name,L"Nokia")) {
- i->hinst = plugin.hDllInstance;
- i->resourceId = IDR_NOKIA_ICON;
- }
- break;
- }
- case DEVICE_SUPPORTED_METADATA:
- return noMetadata ? 0x8f : (0xffef | (requiresALB?SUPPORTS_ALBUMART:0));
- case DEVICE_DOES_NOT_SUPPORT_EDITING_METADATA:
- return noMetadata ? 1 : 0;
- case DEVICE_REFRESH:
- {
- bool nm = noMetadata;
- IWMDMDevice3* d = WMDevice;
- d->AddRef();
- Close();
- new P4SDevice(d,nm);
- d->Release();
- }
- return 0;
- case DEVICE_SUPPORTS_VIDEO:
- return 1;
- case DEVICE_GET_ICON:
- {
- if (param2 <= 16 && param3 <= 16)
- {
- int resourceId;
- wchar_t *buffer;
- if(wcsstr(name,L"Zen"))
- resourceId = IDR_CREATIVE_ZEN_ICON;
- else if (wcsstr(name,L"Nokia"))
- resourceId = IDR_NOKIA_ICON;
- else
- resourceId = 0;
-
- buffer = (wchar_t *)param4;
- if (NULL != buffer &&
- FALSE == FormatResProtocol(MAKEINTRESOURCE(resourceId), RT_RCDATA, buffer, 260))
- {
- buffer[0] = L'\0';
- }
- }
- }
- break;
- }
- return 0;
- }
|