#include "ASDevice.h" #include 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); } } Playlist::Playlist(const wchar_t * path, LPCE_FIND_DATA f) { _snwprintf(fn,MAX_PATH,L"%s\\%s",path,f->cFileName); wchar_t * ext = wcsrchr(f->cFileName,L'.'); if(ext) *ext=0; lstrcpyn(name,f->cFileName,fieldlen); } Playlist::Playlist(const wchar_t * name0) { lstrcpyn(name,name0,fieldlen); fn[0]=0; } #define ASSIGNLARGE(r,h,l) {ULARGE_INTEGER li; li.HighPart = h; li.LowPart = l; r=li.QuadPart;} Song::Song(const wchar_t * path0, LPCE_FIND_DATA f, bool video) : track(-1), video(video) { artist[0]=album[0]=title[0]=fn[0]=0; ASSIGNLARGE(size,f->nFileSizeHigh,f->nFileSizeLow); // first, fill in artist and album wchar_t *path = _wcsdup(path0); wchar_t *a = wcsrchr(path,L'\\'); if(a && a-1 != path) { lstrcpyn(album,a+1,fieldlen); *a=0; a = wcsrchr(path,L'\\'); if(a && a-1 != path) lstrcpyn(artist,a+1,fieldlen); } // now parse out the title _snwprintf(fn,MAX_PATH,L"%s\\%s",path0,f->cFileName); wchar_t * ext = wcsrchr(f->cFileName,L'.'); if(ext) *ext=0; wchar_t * p = f->cFileName; if(memcmp(artist,p,wcslen(artist)*sizeof(wchar_t))==0) p+=wcslen(artist); while(p && *p && (*p==L'.' || *p==L'_' || *p==L'-' || *p==L' ')) p++; track = wcstoul(p,&p,10); while(p && *p && (*p==L'.' || *p==L'_' || *p==L'-' || *p==L' ')) p++; lstrcpyn(title,p,fieldlen); if(title[0]==0) lstrcpyn(title,f->cFileName,fieldlen); free(path); } Song::Song() : video(false) {} void ASDevice::Find(const wchar_t * path) { wchar_t fpath[MAX_PATH] = {0}; wsprintf(fpath,L"%s\\*",path); CE_FIND_DATA f = {0}; HANDLE h = pISession->CeFindFirstFile(fpath,&f); if(h == INVALID_HANDLE_VALUE) return; do { if(f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { wchar_t path2[MAX_PATH] = {0}; wsprintf(path2,L"%s\\%s",path,f.cFileName); Find(path2); } else FoundFile(path,&f); } while(pISession->CeFindNextFile(h,&f)); pISession->CeFindClose(h); } void ASDevice::FoundFile(const wchar_t * path, LPCE_FIND_DATA f) { wchar_t * ext = wcsrchr(f->cFileName,L'.'); if(!_wcsicmp(ext,L".mp3") || !_wcsicmp(ext,L".wma")) playlists[0]->songs.push_back(new Song(path,f,false)); if(!_wcsicmp(ext,L".avi") || !_wcsicmp(ext,L".wmv") || !_wcsicmp(ext,L".asf") || !_wcsicmp(ext,L".mpg") || !_wcsicmp(ext,L".mpeg")) playlists[0]->songs.push_back(new Song(path,f,true)); else if(!_wcsicmp(ext,L".asx")) playlists.push_back(new Playlist(path,f)); } void fixTagsForXML(wchar_t* dest, const wchar_t *cstr, const int len) { int tindex = 0; wchar_t *temp = (wchar_t*)calloc(len, sizeof(wchar_t)); for(int i=0;i'): { if(tindex < len-4) { temp[tindex++] = '&'; temp[tindex++] = 'g'; temp[tindex++] = 't'; temp[tindex] = ';'; } else temp[tindex] = ' '; //no room break; } case(L'\"'): { if(tindex < len-4) { temp[tindex++] = '&'; temp[tindex++] = 'q'; temp[tindex++] = 'u'; temp[tindex++] = 'o'; temp[tindex++] = 't'; temp[tindex] = ';'; } else temp[tindex] = ' '; //no room break; } case(L'\''): { if(tindex < len-4) { temp[tindex++] = '&'; temp[tindex++] = 'a'; temp[tindex++] = 'p'; temp[tindex++] = 'o'; temp[tindex++] = 's'; temp[tindex] = ';'; } else temp[tindex] = ' '; //no room break; } default: { temp[tindex] = cstr[i]; break; } } if(cstr[i] == 0) break; tindex++; } wcsncpy(dest, temp, len); free(temp); } void ASDevice::WritePlaylist(Playlist * pl) { #define CePutws(x,h) pISession->CeWriteFile(h,x,(DWORD)wcslen(x)*sizeof(wchar_t),&w,NULL) #define CePuts(x,h) pISession->CeWriteFile(h,x,(DWORD)strlen(x)*sizeof(char),&w,NULL) HANDLE h = pISession->CeCreateFile(pl->fn,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,TRUNCATE_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(h == INVALID_HANDLE_VALUE) return; std::vector *songs = &pl->songs; int l=(int)songs->size(); DWORD w; CePuts("\r\n",h); for(int j=0; jat(j)->fn,sizeof(safe)/sizeof(wchar_t)); AutoChar fn(safe); CePuts(fn,h); CePuts("\"/>\r\n",h); } CePuts("",h); pISession->CeCloseHandle(h); #undef CePutws #undef CePuts } struct mplSearch { bool operator()(Song*& a,Song*& b) { return _wcsicmp(a->fn,b->fn)<0; } }; struct mplSearch2 { bool operator()(Song*& a,Song* b) { return _wcsicmp(a->fn,b->fn)<0; } }; waServiceFactory *parserFactory; class plread : public ifc_xmlreadercallback { public: Playlist * pl; Playlist * mpl; plread(Playlist * pl,Playlist * mpl) : pl(pl),mpl(mpl) {} void StartTag(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params) { if(!wcscmp(xmlpath,L"ASX\fENTRY\fREF")) { const wchar_t* path = params->getItemValue(L"HREF"); int l= (int)mpl->songs.size(); Song s; lstrcpyn(s.fn,path,MAX_PATH); std::vector::iterator p = std::lower_bound(mpl->songs.begin(),mpl->songs.end(),&s,mplSearch2()); int f = (int)(p - mpl->songs.begin()); if(f >= 0 && f < (int)mpl->songs.size()) { Song * found = mpl->songs[f]; if(!_wcsicmp(found->fn,s.fn)) pl->songs.push_back(found); } } } RECVS_DISPATCH; }; #define CBCLASS plread START_DISPATCH; VCB(ONSTARTELEMENT, StartTag) END_DISPATCH; #undef CBCLASS void ASDevice::ReadPlaylist(Playlist * pl) { if(!parserFactory) return; obj_xml * parser = (obj_xml *)parserFactory->getInterface(); if(!parser) return; HANDLE h = pISession->CeCreateFile(pl->fn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); if(h == INVALID_HANDLE_VALUE) { parserFactory->releaseInterface(parser); return; } plread cb(pl,playlists[0]); parser->xmlreader_open(); parser->xmlreader_registerCallback(L"ASX\fENTRY\f*",&cb); for(;;) { char buf[32768] = {0}; DWORD read = 0; pISession->CeReadFile(h,buf,sizeof(buf),&read,NULL); if(read == 0) break; parser->xmlreader_feed(buf,read); } parserFactory->releaseInterface(parser); pISession->CeCloseHandle(h); } static void findStorageCard(IRAPISession *pISession,wchar_t *storageCard) { ULARGE_INTEGER fa={0},rootTotal={0},ft={0}; pISession->CeGetDiskFreeSpaceEx(L"\\",&fa,&rootTotal,&ft); wchar_t *fpath = L"\\*"; CE_FIND_DATA f; HANDLE h = pISession->CeFindFirstFile(fpath,&f); if(h == INVALID_HANDLE_VALUE) return; do { if(f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY/* && wcscmp(f.cFileName,L"Storage Card")*/) { ULARGE_INTEGER folderTotal={0}; wchar_t path[MAX_PATH] = L"\\"; wcscat(path,f.cFileName); pISession->CeGetDiskFreeSpaceEx(path,&fa,&folderTotal,&ft); if(folderTotal.QuadPart > rootTotal.QuadPart) { rootTotal = folderTotal; wcsncpy(storageCard,path,MAX_PATH); } } } while(pISession->CeFindNextFile(h,&f)); pISession->CeFindClose(h); } ASDevice::ASDevice(IRAPIDevice *pIDevice,IRAPISession *pISession) : pIDevice(pIDevice), pISession(pISession), transferQueueSize(0) { pIDevice->AddRef(); pIDevice->GetDeviceInfo(&devInfo); pmpDeviceLoading load={this,0}; 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),devInfo.bstrName); load.UpdateCaption(buf,load.context); } //find where playlists and music are stored... wchar_t storageCard[MAX_PATH]=L""; findStorageCard(pISession,storageCard); wsprintf(musicFolder,L"%s\\Music",storageCard); wsprintf(videoFolder,L"%s\\My Documents\\My Videos",storageCard); wsprintf(playlistFolder,L"%s\\Playlists",storageCard); wcsncpy(playlistFormat,L".asx",16); // default values found. Fill in real values { wchar_t inifile[MAX_PATH] = {0}; const char * iniDirectory = (const char*)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETINIDIRECTORY); wchar_t name[256] = {0}; lstrcpyn(name,devInfo.bstrName,256); removebadchars(name); wsprintf(inifile,L"%s\\Plugins\\ml\\ml_pmp_device_%s.ini",(wchar_t*)AutoWide(iniDirectory),name); wchar_t * def = _wcsdup(musicFolder); GetPrivateProfileString(L"pmp_activesync",L"musicfolder",def,musicFolder,MAX_PATH,inifile); free(def); def = _wcsdup(videoFolder); GetPrivateProfileString(L"pmp_activesync",L"videofolder",def,videoFolder,MAX_PATH,inifile); free(def); def = _wcsdup(playlistFolder); GetPrivateProfileString(L"pmp_activesync",L"playlistfolder",def,playlistFolder,MAX_PATH,inifile); free(def); } playlists.push_back(new Playlist(devInfo.bstrName)); Find(musicFolder); Find(videoFolder); Find(playlistFolder); std::sort(playlists[0]->songs.begin(),playlists[0]->songs.end(),mplSearch()); parserFactory = plugin.service->service_getServiceByGuid(obj_xmlGUID); for(unsigned int i=1; iAddAcceptableFormat(L"mp3"); transcoder->AddAcceptableFormat(L"wma"); transcoder->AddAcceptableFormat(L"wmv"); transcoder->AddAcceptableFormat(L"avi"); transcoder->AddAcceptableFormat(L"asf"); transcoder->AddAcceptableFormat(L"mpeg"); transcoder->AddAcceptableFormat(L"mpg"); } ASDevice::~ASDevice() { Playlist *mpl = playlists[ 0 ]; unsigned int l = (unsigned int)mpl->songs.size(); for ( unsigned int i = 0; i < l; i++ ) { delete mpl->songs[ i ]; } for ( unsigned int j = 0; j < playlists.size(); j++ ) { delete playlists[ j ]; } for ( int k = 0; k < devices.size(); k++ ) { if ( devices[ k ] == this ) { devices.erase( devices.begin() + k ); k--; } } pIDevice->Release(); pISession->Release(); SysFreeString( devInfo.bstrName ); SysFreeString( devInfo.bstrPlatform ); SendMessage( plugin.hwndPortablesParent, WM_PMP_IPC, (WPARAM)transcoder, PMP_IPC_RELEASE_TRANSCODER ); } __int64 ASDevice::getDeviceCapacityAvailable() { if(devInfo.dwOsVersionMajor >= 5) { ULARGE_INTEGER fa={0},t={0},ft={0}; pISession->CeGetDiskFreeSpaceEx(musicFolder,&fa,&t,&ft); return fa.QuadPart; } else { STORE_INFORMATION s; pISession->CeGetStoreInformation(&s); return s.dwFreeSize; } } __int64 ASDevice::getDeviceCapacityTotal() { if(devInfo.dwOsVersionMajor >= 5) { ULARGE_INTEGER fa={0},t={0},ft={0}; pISession->CeGetDiskFreeSpaceEx(musicFolder,&fa,&t,&ft); return t.QuadPart; } else { STORE_INFORMATION s; pISession->CeGetStoreInformation(&s); return s.dwStoreSize; } } void ASDevice::Eject() { ejectedDevice *e = (ejectedDevice *)calloc(1, sizeof(ejectedDevice)); e->id = devInfo.DeviceId; e->marked = true; ejected.push_back(e); Close(); } void ASDevice::Close() { SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICEDISCONNECTED); delete this; } int ASDevice::transferTrackToDevice(const itemRecordW * track,void * callbackContext,void (*callback)(void * callbackContext, wchar_t * status),songid_t * songid,int * killswitch) { wchar_t ext[10]={0}; wchar_t file[2048]={0}; wcsncpy(file,track->filename,2048); {wchar_t * e = wcsrchr(file,L'.'); if(e) wcsncpy(ext,e+1,10);} bool deletefile = false; if(transcoder->ShouldTranscode(file)) { wchar_t newfile[MAX_PATH] = {0}; transcoder->CanTranscode(file,ext); transcoder->GetTempFilePath(ext,newfile); if(transcoder->TranscodeFile(file,newfile,killswitch,callback,callbackContext)) return -1; wcsncpy(file,newfile,2048); deletefile=true; } callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING)); bool video = !_wcsicmp(ext,L"wmv") || !_wcsicmp(ext,L"avi"); int len = (int)(wcslen(musicFolder)+wcslen(track->artist)+wcslen(track->album)+wcslen(track->title)+100); wchar_t *path = (wchar_t*)calloc(len, sizeof(wchar_t)); wchar_t *artist = _wcsdup(track->artist); wchar_t *album = _wcsdup(track->album); wchar_t *title = _wcsdup(track->title); removebadchars(artist); removebadchars(album); removebadchars(title); if(video) { wcsncpy(path,videoFolder,len); pISession->CeCreateDirectory(path,NULL); wsprintf(path+wcslen(path),L"\\%s - %s.%s",artist,title,ext); } else { wcsncpy(path,musicFolder,len); pISession->CeCreateDirectory(path,NULL); wcscat(path,L"\\"); wcscat(path,artist); pISession->CeCreateDirectory(path,NULL); wcscat(path,L"\\"); wcscat(path,album); pISession->CeCreateDirectory(path,NULL); wsprintf(path+wcslen(path),L"\\%02d - %s.%s",track->track,title,ext); } free(artist); free(album); free(title); FILE *f = _wfopen(file,L"rb"); if(!f) { callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_CANNOT_OPEN_LOCAL_FILE)); return -1; } HANDLE h = pISession->CeCreateFile(path,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); if(h == INVALID_HANDLE_VALUE) { callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_CANNOT_OPEN_FILE_ON_DEVICE)); fclose(f); return -1; } fseek(f,0,2); int error=0; int size = ftell(f); int pc = size/100; fseek(f,0,0); int written=0,lastupdate=0; for(;;) { char buf[32768] = {0}; int l = (int)fread(buf,1,sizeof(buf),f); if(!l) break; DWORD wl=0; pISession->CeWriteFile(h,buf,l,&wl,NULL); if(wl != l) { callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_ERROR_WRITING_FILE)); error=1; break; } written += l; if(written - lastupdate > pc) { lastupdate = written; wchar_t buf[100] = {0}; wsprintf(buf,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING_PERCENT),written/(size/100)); callback(callbackContext,buf); } } fclose(f); pISession->CeCloseHandle(h); if(deletefile) _wunlink(file); if(!error) { callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_DONE)); Song * s = new Song; lstrcpyn(s->fn,path,MAX_PATH); lstrcpyn(s->album,track->album,fieldlen); lstrcpyn(s->artist,track->artist,fieldlen); lstrcpyn(s->title,track->title,fieldlen); s->track = track->track; s->size = size; s->video = video; *songid = (songid_t)s; } free(path); return error?-1:0; } 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 extentionSupported(wchar_t * ext) { if(!ext) return false; bool supported=false; if(!_wcsicmp(ext,L".mp3") || !_wcsicmp(ext,L".wma")) supported=true; if(!_wcsicmp(ext,L".avi") || !_wcsicmp(ext,L".wmv")) supported=true; return supported; } int ASDevice::trackAddedToTransferQueue(const itemRecordW * track) { __int64 s = getTrackSizeOnDevice(track); if(!s) return -2; __int64 avail = getDeviceCapacityAvailable(); __int64 cmp = transferQueueSize; cmp += s; if(cmp > avail) return -1; else { transferQueueSize += s; return 0; } } void ASDevice::trackRemovedFromTransferQueue(const itemRecordW * track) { transferQueueSize -= getTrackSizeOnDevice(track); } __int64 ASDevice::getTrackSizeOnDevice(const itemRecordW * track) { if(transcoder->ShouldTranscode(track->filename)) { int k = transcoder->CanTranscode(track->filename); if(k != -1 && k != 0) return k; } wchar_t * ext = wcsrchr(track->filename,L'.'); if(!extentionSupported(ext)) return 0; return fileSize(track->filename); } void ASDevice::deleteTrack(songid_t songid) { Song * song = (Song*)songid; if(!pISession->CeDeleteFile(song->fn)) return; for(unsigned int i=0; isongs.size(); for(int j=0; jsongs[j] == song) { playlists[i]->songs.erase(playlists[i]->songs.begin() + j); j--; l--; playlists[i]->dirty=true; } } } delete song; } void ASDevice::commitChanges() { for(unsigned int i=1; idirty) { WritePlaylist(playlists[i]); playlists[i]->dirty=false; } } int ASDevice::getPlaylistCount() { return (int)playlists.size(); } void ASDevice::getPlaylistName(int playlistnumber, wchar_t * buf, int len) { lstrcpyn(buf,playlists[playlistnumber]->name,len); } int ASDevice::getPlaylistLength(int playlistnumber) { return (int)playlists[playlistnumber]->songs.size(); } songid_t ASDevice::getPlaylistTrack(int playlistnumber,int songnum) { return (songid_t)playlists[playlistnumber]->songs[songnum]; } void ASDevice::setPlaylistName(int playlistnumber, const wchar_t * buf) { Playlist * pl = playlists[playlistnumber]; lstrcpyn(pl->name,buf,fieldlen); wchar_t * oldname = _wcsdup(pl->fn); wchar_t * name = _wcsdup(buf); removebadchars(name); wsprintf(pl->fn,L"%s\\%s.%s",playlistFolder,name,playlistFormat); free(name); pISession->CeMoveFile(oldname,pl->fn); free(oldname); } void ASDevice::playlistSwapItems(int playlistnumber, int posA, int posB) { std::vector &songs = playlists[playlistnumber]->songs; Song * a = songs[posA]; Song * b = songs[posB]; songs[posA] = b; songs[posB] = a; playlists[playlistnumber]->dirty=true; } #define CMPFIELDS(x) { int v = lstrcmpi(a->x,b->x); if(v) return v<0; } #define CMPINTFIELDS(x) { int v = a->x-b->x; if(v) return v<0; } typedef struct PlaylistItemSort { int use_by; bool operator()(Song*& a,Song*& b) { int x; for (x = 0; x < 4; x ++) { if (use_by == SORTBY_TITLE) // title -> artist -> album -> disc -> track { CMPFIELDS(title); use_by=SORTBY_ARTIST; } else if (use_by == SORTBY_ARTIST) // artist -> album -> disc -> track -> title { CMPFIELDS(artist); use_by=SORTBY_ALBUM; } else if (use_by == SORTBY_ALBUM) // album -> disc -> track -> title -> artist { CMPFIELDS(album); use_by=SORTBY_TRACKNUM; } else if (use_by == SORTBY_TRACKNUM) // track -> title -> artist -> album -> disc { CMPINTFIELDS(track); use_by=SORTBY_TITLE; } else break; // no sort order? } return false; } } PlaylistItemSort; #undef CMPFIELDS #undef CMPINTFIELDS void ASDevice::sortPlaylist(int playlistnumber, int sortBy) { PlaylistItemSort sort; sort.use_by = sortBy; std::sort(playlists[playlistnumber]->songs.begin(),playlists[playlistnumber]->songs.end(),sort); playlists[playlistnumber]->dirty=true; } void ASDevice::addTrackToPlaylist(int playlistnumber, songid_t songid){ playlists[playlistnumber]->songs.push_back((Song*)songid); playlists[playlistnumber]->dirty=true; } void ASDevice::removeTrackFromPlaylist(int playlistnumber, int songnum) { playlists[playlistnumber]->songs.erase(playlists[playlistnumber]->songs.begin() + songnum); playlists[playlistnumber]->dirty=true; } void ASDevice::deletePlaylist(int playlistnumber) { pISession->CeDeleteFile(playlists[playlistnumber]->fn); delete playlists[playlistnumber]; playlists.erase(playlists.begin() + playlistnumber); } int ASDevice::newPlaylist(const wchar_t * name0) { pISession->CeCreateDirectory(playlistFolder,NULL); Playlist* pl = new Playlist(name0); wchar_t * name = _wcsdup(name0); removebadchars(name); wsprintf(pl->fn,L"%s\\%s.%s",playlistFolder,name,playlistFormat); free(name); pl->dirty=true; playlists.push_back(pl); return (int)playlists.size()-1; } void ASDevice::getTrackArtist(songid_t songid, wchar_t * buf, int len) { lstrcpyn(buf,((Song*)songid)->artist,len); } void ASDevice::getTrackAlbum(songid_t songid, wchar_t * buf, int len) { lstrcpyn(buf,((Song*)songid)->album,len); } void ASDevice::getTrackTitle(songid_t songid, wchar_t * buf, int len) { lstrcpyn(buf,((Song*)songid)->title,len); } int ASDevice::getTrackTrackNum(songid_t songid) { return ((Song*)songid)->track; } __int64 ASDevice::getTrackSize(songid_t songid) { return ((Song*)songid)->size; } void ASDevice::getTrackExtraInfo(songid_t songid, const wchar_t * field, wchar_t * buf, int len) { if(!wcscmp(field,FIELD_EXTENSION)) { Song * s = (Song *)songid; wchar_t * ext = wcsrchr(s->fn,L'.'); if(ext) { ext++; lstrcpyn(buf,ext,len); } } } int ASDevice::copyToHardDrive(songid_t song,wchar_t * path,void * callbackContext,void (*callback)(void * callbackContext, wchar_t * status),int * killswitch) { Song * s = (Song*)song; wchar_t * ext = wcsrchr(s->fn,L'.'); if(ext && wcslen(ext)<10) wcscat(path,ext); callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING)); FILE * f = _wfopen(path,L"wb"); if(!f) { callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_CANNOT_OPEN_DESTINATION)); return -1; } HANDLE h = pISession->CeCreateFile(s->fn,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); if(h == INVALID_HANDLE_VALUE) { callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_CANNOT_OPEN_FILE_ON_DEVICE)); fclose(f); return -1; } int error=0; int pc = (int)(s->size/100); int written=0,lastupdate=0; for(;;) { char buf[32768] = {0}; DWORD read=0; pISession->CeReadFile(h,buf,sizeof(buf),&read,NULL); if(!read) break; int wr = (int)fwrite(buf,1,read,f); if(wr != read) { callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_ERROR_WRITING_FILE)); error=1; break; } written += read; if(written - lastupdate > pc) { lastupdate = written; wchar_t buf[100] = {0}; wsprintf(buf,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING),written/(s->size/100)); callback(callbackContext,buf); } } pISession->CeCloseHandle(h); fclose(f); if(!error) { callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_DONE)); return 0; } else return -1; } static BOOL CALLBACK config_dialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam); intptr_t ASDevice::extraActions(intptr_t param1, intptr_t param2, intptr_t param3,intptr_t param4) { switch(param1) { case DEVICE_SET_ICON: { MLTREEIMAGE * i = (MLTREEIMAGE*)param2; i->hinst = plugin.hDllInstance; i->resourceId = IDR_ACTIVESYNC_ICON; } break; case DEVICE_SUPPORTED_METADATA: return 0x8f; case DEVICE_DOES_NOT_SUPPORT_EDITING_METADATA: return 1; case DEVICE_GET_PREFS_DIALOG: if(param3 == 0) { pref_tab * p = (pref_tab *)param2; p->hinst = WASABI_API_LNG_HINST; p->dlg_proc = (DLGPROC)config_dialogProc; p->res_id = IDD_CONFIG; lstrcpyn(p->title,WASABI_API_LNGSTRINGW(IDS_ADVANCED),100); } break; case DEVICE_SUPPORTS_VIDEO: return 1; } return 0; } static BOOL CALLBACK config_dialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam) { static ASDevice * dev; switch(uMsg) { case WM_INITDIALOG: { prefsParam* p = (prefsParam*)lParam; dev = (ASDevice*)p->dev; p->config_tab_init(hwndDlg,p->parent); SetDlgItemText(hwndDlg,IDC_FOLDER_MUSIC,dev->musicFolder); SetDlgItemText(hwndDlg,IDC_FOLDER_VIDEO,dev->videoFolder); SetDlgItemText(hwndDlg,IDC_FOLDER_PLAYLIST,dev->playlistFolder); } break; case WM_DESTROY: { GetDlgItemText(hwndDlg,IDC_FOLDER_MUSIC,dev->musicFolder,MAX_PATH); GetDlgItemText(hwndDlg,IDC_FOLDER_VIDEO,dev->videoFolder,MAX_PATH); GetDlgItemText(hwndDlg,IDC_FOLDER_PLAYLIST,dev->playlistFolder,MAX_PATH); wchar_t *inifile = (wchar_t*)SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)dev,PMP_IPC_GET_INI_FILE); #if 1 wchar_t inifil[MAX_PATH] = {0}; if(!inifile) { inifile=inifil; const char * iniDirectory = (const char*)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETINIDIRECTORY); wchar_t name[256] = {0}; lstrcpyn(name,dev->devInfo.bstrName,256); removebadchars(name); wsprintf(inifile,L"%s\\Plugins\\ml\\ml_pmp_device_%s.ini",(wchar_t*)AutoWide(iniDirectory),name); } #endif if(inifile) { WritePrivateProfileString(L"pmp_activesync",L"musicfolder",dev->musicFolder,inifile); WritePrivateProfileString(L"pmp_activesync",L"videofolder",dev->videoFolder,inifile); WritePrivateProfileString(L"pmp_activesync",L"playlistfolder",dev->playlistFolder,inifile); } } break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_RESCAN: config_dialogProc(hwndDlg,WM_DESTROY,0,0); dev->Close(); break; } break; } return 0; }