123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798 |
- #include "ASDevice.h"
- #include <vector>
- 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<len && tindex<len;i++)
- {
- switch(cstr[i])
- {
- case(L'&'):
- if(tindex < len-5)
- {
- temp[tindex++] = '&';
- temp[tindex++] = 'a';
- temp[tindex++] = 'm';
- temp[tindex++] = 'p';
- temp[tindex] = ';';
- }
- else temp[tindex] = ' '; //no room
- break;
- case(L'<'):
- {
- if(tindex < len-4)
- {
- temp[tindex++] = '&';
- temp[tindex++] = 'l';
- temp[tindex++] = 't';
- temp[tindex] = ';';
- }
- else temp[tindex] = ' '; //no room
- break;
- }
- case(L'>'):
- {
- 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<Song*> *songs = &pl->songs;
- int l=(int)songs->size();
- DWORD w;
- CePuts("<asx version=\"3.0\">\r\n",h);
- for(int j=0; j<l; j++) {
- CePuts("<entry><ref href=\"",h);
- wchar_t safe[fieldlen*2] = {0};
- fixTagsForXML(safe,songs->at(j)->fn,sizeof(safe)/sizeof(wchar_t));
- AutoChar fn(safe);
- CePuts(fn,h);
- CePuts("\"/></entry>\r\n",h);
- }
- CePuts("</asx>",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<Song*>::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; i<playlists.size(); i++)
- ReadPlaylist(playlists[i]);
- SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICECONNECTED);
- transcoder = (Transcoder*)SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_GET_TRANSCODER);
- transcoder->AddAcceptableFormat(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; i<playlists.size(); i++)
- {
- unsigned int l = (unsigned int)playlists[i]->songs.size();
- for(int j=0; j<l; j++)
- {
- if(playlists[i]->songs[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; i<playlists.size(); i++) if(playlists[i]->dirty) { 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<Song*> &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;
- }
|