Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions
@@ -0,0 +1,798 @@
#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;
}
@@ -0,0 +1,172 @@
#define _WIN32_DCOM
#include <winsock2.h>
#include <windows.h>
#include <windowsx.h>
#include <rapi2.h>
#include <shlobj.h>
//#include <vector>
#include <algorithm>
#include <vector>
#include "../Winamp/wa_ipc.h"
#include "../Plugins/General/gen_ml/ml.h"
#include "../Plugins/Library/ml_pmp/pmp.h"
#include "../Plugins/Library/ml_pmp/transcoder.h"
#include "../nu/AutoWide.h"
#include "../nu/AutoChar.h"
#include <api/service/waservicefactory.h>
#include "../playlist/ifc_playlistloader.h"
#include "../xml/ifc_xmlreadercallback.h"
#include "../xml/obj_xml.h"
#include "../xml/api__xml.h"
#include "../Agave/Language/api_language.h"
#include "resource.h"
typedef struct {
RAPIDEVICEID id;
bool marked;
} ejectedDevice;
extern PMPDevicePlugin plugin;
extern std::vector<ejectedDevice*> ejected;
#define fieldlen 128
class Song {
public:
wchar_t artist[fieldlen],album[fieldlen],title[fieldlen];
wchar_t fn[MAX_PATH];
int track;
__int64 size;
bool video;
Song(const wchar_t * path, LPCE_FIND_DATA f, bool video);
Song();
};
class Playlist {
public:
std::vector<Song*> songs;
wchar_t name[fieldlen];
wchar_t fn[MAX_PATH];
bool dirty;
Playlist(const wchar_t * path, LPCE_FIND_DATA f);
Playlist(const wchar_t * name);
};
class ASDevice : public Device {
public:
wchar_t musicFolder[MAX_PATH];
wchar_t videoFolder[MAX_PATH];
wchar_t playlistFolder[MAX_PATH];
wchar_t playlistFormat[16];
IRAPIDevice *pIDevice;
IRAPISession *pISession;
Transcoder * transcoder;
RAPI_DEVICEINFO devInfo;
__int64 transferQueueSize;
std::vector<Playlist*> playlists;
void Find(const wchar_t * dir);
void FoundFile(const wchar_t * path, LPCE_FIND_DATA f);
void WritePlaylist(Playlist * pl);
void ReadPlaylist(Playlist * pl);
ASDevice(IRAPIDevice *pIDevice,IRAPISession *pISession);
~ASDevice();
virtual __int64 getDeviceCapacityAvailable(); // in bytes
virtual __int64 getDeviceCapacityTotal(); // in bytes
virtual void Eject();
virtual void Close(); // save any changes, and call PMP_IPC_DEVICEDISCONNECTED AND delete this;
// return 0 for success, -1 for failed or cancelled
virtual int transferTrackToDevice(const itemRecordW * track, // the track to transfer
void * callbackContext, //pass this to the callback
void (*callback)(void * callbackContext, wchar_t * status), // call this every so often so the GUI can be updated. Including when finished!
songid_t * songid, // fill in the songid when you are finished
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
);
virtual int trackAddedToTransferQueue(const itemRecordW * track); // return 0 to accept, -1 for "not enough space", -2 for "incorrect format"
virtual void trackRemovedFromTransferQueue(const itemRecordW * track);
// return the amount of space that will be taken up on the device by the track (once it has been tranferred)
// or 0 for incompatable. This is usually the filesize, unless you are transcoding. An estimate is acceptable.
virtual __int64 getTrackSizeOnDevice(const itemRecordW * track);
virtual void deleteTrack(songid_t songid); // physically remove from device. Be sure to remove it from all the playlists!
virtual void commitChanges(); // optional. Will be called at a good time to save changes
virtual int getPlaylistCount(); // always at least 1. playlistnumber 0 is the Master Playlist containing all tracks.
// PlaylistName(0) should return the name of the device.
virtual void getPlaylistName(int playlistnumber, wchar_t * buf, int len);
virtual int getPlaylistLength(int playlistnumber);
virtual songid_t getPlaylistTrack(int playlistnumber,int songnum); // returns a songid
virtual void setPlaylistName(int playlistnumber, const wchar_t * buf); // with playlistnumber==0, set the name of the device.
virtual void playlistSwapItems(int playlistnumber, int posA, int posB); // swap the songs at position posA and posB
virtual void sortPlaylist(int playlistnumber, int sortBy);
virtual void addTrackToPlaylist(int playlistnumber, songid_t songid); // adds songid to the end of the playlist
virtual void removeTrackFromPlaylist(int playlistnumber, int songnum); //where songnum is the position of the track in the playlist
virtual void deletePlaylist(int playlistnumber);
virtual int newPlaylist(const wchar_t * name); // create empty playlist, returns playlistnumber. -1 for failed.
virtual void getTrackArtist(songid_t songid, wchar_t * buf, int len);
virtual void getTrackAlbum(songid_t songid, wchar_t * buf, int len);
virtual void getTrackTitle(songid_t songid, wchar_t * buf, int len);
virtual int getTrackTrackNum(songid_t songid);
virtual int getTrackDiscNum(songid_t songid){return -1;}
virtual void getTrackGenre(songid_t songid, wchar_t * buf, int len){buf[0]=0;}
virtual int getTrackYear(songid_t songid){return -1;}
virtual __int64 getTrackSize(songid_t songid); // in bytes
virtual int getTrackLength(songid_t songid){return -1;} // in millisecs
virtual int getTrackBitrate(songid_t songid){return -1;} // in kbps
virtual int getTrackPlayCount(songid_t songid){return 0;}
virtual int getTrackRating(songid_t songid){return 0;} //0-5
virtual __time64_t getTrackLastPlayed(songid_t songid){return 0;} // in unix time format
virtual __time64_t getTrackLastUpdated(songid_t songid){return 0;} // in unix time format
virtual int getTrackType(songid_t songid) { return ((Song *)songid)->video?1:0; }
virtual void getTrackExtraInfo(songid_t songid, const wchar_t * field, wchar_t * buf, int len); //optional
// feel free to ignore any you don't support
virtual void setTrackArtist(songid_t songid, const wchar_t * value){}
virtual void setTrackAlbum(songid_t songid, const wchar_t * value){}
virtual void setTrackTitle(songid_t songid, const wchar_t * value){}
virtual void setTrackTrackNum(songid_t songid, int value){}
virtual void setTrackDiscNum(songid_t songid, int value){}
virtual void setTrackGenre(songid_t songid, const wchar_t * value){}
virtual void setTrackYear(songid_t songid, int year){}
virtual void setTrackPlayCount(songid_t songid, int value){}
virtual void setTrackRating(songid_t songid, int value){}
virtual void setTrackLastPlayed(songid_t songid, __time64_t value){} // in unix time format
virtual void setTrackLastUpdated(songid_t songid, __time64_t value){} // in unix time format
virtual void setTrackExtraInfo(songid_t songid, const wchar_t * field, const wchar_t * value) {}; //optional
virtual bool playTracks(songid_t * songidList, int listLength, int startPlaybackAt, bool enqueue){return false;} // return false if unsupported
virtual intptr_t extraActions(intptr_t param1, intptr_t param2, intptr_t param3,intptr_t param4);
// new methods as of PMPHDR_VER 0x002
virtual bool copyToHardDriveSupported() {return true;}
virtual __int64 songSizeOnHardDrive(songid_t song) {return getTrackSize(song);} // how big a song will be when copied back. Return -1 for not supported.
virtual int copyToHardDrive(songid_t song, // the song to copy
wchar_t * path, // path to copy to, in the form "c:\directory\song". The directory will already be created, you must append ".mp3" or whatever to this string! (there is space for at least 10 new characters).
void * callbackContext, //pass this to the callback
void (*callback)(void * callbackContext, wchar_t * status), // call this every so often so the GUI can be updated. Including when finished!
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
); // -1 for failed/not supported. 0 for success.
};
extern std::vector<ASDevice*> devices;
@@ -0,0 +1,286 @@
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
/* File created by MIDL compiler version 6.00.0361 */
/* at Fri Sep 17 22:09:50 2004
*/
/* Compiler settings for ..\IRAPIStream.idl:
Oicf, W1, Zp8, env=Win32 (32b run)
protocol : dce , ms_ext, c_ext, robust
error checks: allocation ref bounds_check enum stub_data
VC __declspec() decoration level:
__declspec(uuid()), __declspec(selectany), __declspec(novtable)
DECLSPEC_UUID(), MIDL_INTERFACE()
*/
//@@MIDL_FILE_HEADING( )
#pragma warning( disable: 4049 ) /* more than 64k source lines */
/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 475
#endif
#include "rpc.h"
#include "rpcndr.h"
#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__
#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/
#ifndef __IRAPIStream_h__
#define __IRAPIStream_h__
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
#pragma once
#endif
/* Forward Declarations */
#ifndef __IRAPIStream_FWD_DEFINED__
#define __IRAPIStream_FWD_DEFINED__
typedef interface IRAPIStream IRAPIStream;
#endif /* __IRAPIStream_FWD_DEFINED__ */
/* header files for imported files */
#include "oaidl.h"
#include "ocidl.h"
#include "rapitypes.h"
#ifdef __cplusplus
extern "C"{
#endif
void * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void * );
#ifndef __IRAPIStream_INTERFACE_DEFINED__
#define __IRAPIStream_INTERFACE_DEFINED__
/* interface IRAPIStream */
/* [object][uuid] */
EXTERN_C const IID IID_IRAPIStream;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("449FE623-24B0-454b-A889-129BB05DDBED")
IRAPIStream : public IStream
{
public:
virtual HRESULT STDMETHODCALLTYPE SetRapiStat(
/* [in] */ RAPISTREAMFLAG Flag,
/* [in] */ DWORD dwValue) = 0;
virtual HRESULT STDMETHODCALLTYPE GetRapiStat(
/* [in] */ RAPISTREAMFLAG Flag,
/* [out] */ DWORD *pdwValue) = 0;
};
#else /* C style interface */
typedef struct IRAPIStreamVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IRAPIStream * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IRAPIStream * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IRAPIStream * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Read )(
IRAPIStream * This,
/* [length_is][size_is][out] */ void *pv,
/* [in] */ ULONG cb,
/* [out] */ ULONG *pcbRead);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Write )(
IRAPIStream * This,
/* [size_is][in] */ const void *pv,
/* [in] */ ULONG cb,
/* [out] */ ULONG *pcbWritten);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *Seek )(
IRAPIStream * This,
/* [in] */ LARGE_INTEGER dlibMove,
/* [in] */ DWORD dwOrigin,
/* [out] */ ULARGE_INTEGER *plibNewPosition);
HRESULT ( STDMETHODCALLTYPE *SetSize )(
IRAPIStream * This,
/* [in] */ ULARGE_INTEGER libNewSize);
/* [local] */ HRESULT ( STDMETHODCALLTYPE *CopyTo )(
IRAPIStream * This,
/* [unique][in] */ IStream *pstm,
/* [in] */ ULARGE_INTEGER cb,
/* [out] */ ULARGE_INTEGER *pcbRead,
/* [out] */ ULARGE_INTEGER *pcbWritten);
HRESULT ( STDMETHODCALLTYPE *Commit )(
IRAPIStream * This,
/* [in] */ DWORD grfCommitFlags);
HRESULT ( STDMETHODCALLTYPE *Revert )(
IRAPIStream * This);
HRESULT ( STDMETHODCALLTYPE *LockRegion )(
IRAPIStream * This,
/* [in] */ ULARGE_INTEGER libOffset,
/* [in] */ ULARGE_INTEGER cb,
/* [in] */ DWORD dwLockType);
HRESULT ( STDMETHODCALLTYPE *UnlockRegion )(
IRAPIStream * This,
/* [in] */ ULARGE_INTEGER libOffset,
/* [in] */ ULARGE_INTEGER cb,
/* [in] */ DWORD dwLockType);
HRESULT ( STDMETHODCALLTYPE *Stat )(
IRAPIStream * This,
/* [out] */ STATSTG *pstatstg,
/* [in] */ DWORD grfStatFlag);
HRESULT ( STDMETHODCALLTYPE *Clone )(
IRAPIStream * This,
/* [out] */ IStream **ppstm);
HRESULT ( STDMETHODCALLTYPE *SetRapiStat )(
IRAPIStream * This,
/* [in] */ RAPISTREAMFLAG Flag,
/* [in] */ DWORD dwValue);
HRESULT ( STDMETHODCALLTYPE *GetRapiStat )(
IRAPIStream * This,
/* [in] */ RAPISTREAMFLAG Flag,
/* [out] */ DWORD *pdwValue);
END_INTERFACE
} IRAPIStreamVtbl;
interface IRAPIStream
{
CONST_VTBL struct IRAPIStreamVtbl *lpVtbl;
};
#ifdef COBJMACROS
#define IRAPIStream_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IRAPIStream_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IRAPIStream_Release(This) \
(This)->lpVtbl -> Release(This)
#define IRAPIStream_Read(This,pv,cb,pcbRead) \
(This)->lpVtbl -> Read(This,pv,cb,pcbRead)
#define IRAPIStream_Write(This,pv,cb,pcbWritten) \
(This)->lpVtbl -> Write(This,pv,cb,pcbWritten)
#define IRAPIStream_Seek(This,dlibMove,dwOrigin,plibNewPosition) \
(This)->lpVtbl -> Seek(This,dlibMove,dwOrigin,plibNewPosition)
#define IRAPIStream_SetSize(This,libNewSize) \
(This)->lpVtbl -> SetSize(This,libNewSize)
#define IRAPIStream_CopyTo(This,pstm,cb,pcbRead,pcbWritten) \
(This)->lpVtbl -> CopyTo(This,pstm,cb,pcbRead,pcbWritten)
#define IRAPIStream_Commit(This,grfCommitFlags) \
(This)->lpVtbl -> Commit(This,grfCommitFlags)
#define IRAPIStream_Revert(This) \
(This)->lpVtbl -> Revert(This)
#define IRAPIStream_LockRegion(This,libOffset,cb,dwLockType) \
(This)->lpVtbl -> LockRegion(This,libOffset,cb,dwLockType)
#define IRAPIStream_UnlockRegion(This,libOffset,cb,dwLockType) \
(This)->lpVtbl -> UnlockRegion(This,libOffset,cb,dwLockType)
#define IRAPIStream_Stat(This,pstatstg,grfStatFlag) \
(This)->lpVtbl -> Stat(This,pstatstg,grfStatFlag)
#define IRAPIStream_Clone(This,ppstm) \
(This)->lpVtbl -> Clone(This,ppstm)
#define IRAPIStream_SetRapiStat(This,Flag,dwValue) \
(This)->lpVtbl -> SetRapiStat(This,Flag,dwValue)
#define IRAPIStream_GetRapiStat(This,Flag,pdwValue) \
(This)->lpVtbl -> GetRapiStat(This,Flag,pdwValue)
#endif /* COBJMACROS */
#endif /* C style interface */
HRESULT STDMETHODCALLTYPE IRAPIStream_SetRapiStat_Proxy(
IRAPIStream * This,
/* [in] */ RAPISTREAMFLAG Flag,
/* [in] */ DWORD dwValue);
void __RPC_STUB IRAPIStream_SetRapiStat_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
HRESULT STDMETHODCALLTYPE IRAPIStream_GetRapiStat_Proxy(
IRAPIStream * This,
/* [in] */ RAPISTREAMFLAG Flag,
/* [out] */ DWORD *pdwValue);
void __RPC_STUB IRAPIStream_GetRapiStat_Stub(
IRpcStubBuffer *This,
IRpcChannelBuffer *_pRpcChannelBuffer,
PRPC_MESSAGE _pRpcMessage,
DWORD *_pdwStubPhase);
#endif /* __IRAPIStream_INTERFACE_DEFINED__ */
/* Additional Prototypes for ALL interfaces */
/* end of Additional Prototypes */
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,118 @@
// --------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Module:
//
// rapi.h
//
// Purpose:
//
// Master include file for Windows CE Remote API
//
// --------------------------------------------------------------------------
#ifndef RAPI_H
#define RAPI_H
#include <windows.h>
#include "rapitypes.h"
#include "irapistream.h"
#ifndef UNDER_CE
STDAPI CeRapiInitEx(RAPIINIT*);
STDAPI CeRapiInit();
STDAPI CeRapiUninit();
STDAPI CeRapiGetError(void);
STDAPI CeRapiFreeBuffer(LPVOID);
STDAPI_( HRESULT ) CeRapiInvoke(LPCWSTR, LPCWSTR,DWORD,BYTE *, DWORD *,BYTE **, IRAPIStream **,DWORD);
STDAPI_(CEOID) CeCreateDatabase (LPWSTR, DWORD, WORD, SORTORDERSPEC*);
STDAPI_(BOOL ) CeDeleteDatabase (CEOID);
STDAPI_(BOOL ) CeDeleteRecord (HANDLE, CEOID);
STDAPI_(HANDLE) CeFindFirstDatabase (DWORD);
STDAPI_(CEOID) CeFindNextDatabase (HANDLE);
STDAPI_(BOOL ) CeOidGetInfo (CEOID, CEOIDINFO*);
STDAPI_(HANDLE) CeOpenDatabase (PCEOID, LPWSTR, CEPROPID, DWORD, HWND);
STDAPI_(CEOID) CeReadRecordProps (HANDLE, DWORD, LPWORD, CEPROPID*, LPBYTE*, LPDWORD);
STDAPI_(CEOID) CeSeekDatabase (HANDLE, DWORD, DWORD, LPDWORD);
STDAPI_(BOOL ) CeSetDatabaseInfo (CEOID, CEDBASEINFO*);
STDAPI_(HANDLE) CeFindFirstFile (LPCWSTR, LPCE_FIND_DATA);
STDAPI_(BOOL ) CeFindNextFile (HANDLE, LPCE_FIND_DATA);
STDAPI_(BOOL ) CeFindClose (HANDLE);
STDAPI_(DWORD ) CeGetFileAttributes (LPCWSTR);
STDAPI_(BOOL ) CeSetFileAttributes (LPCWSTR, DWORD);
STDAPI_(HANDLE) CeCreateFile (LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
STDAPI_(BOOL ) CeReadFile (HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
STDAPI_(BOOL ) CeWriteFile (HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
STDAPI_(BOOL ) CeCloseHandle (HANDLE);
STDAPI_(BOOL ) CeFindAllFiles (LPCWSTR, DWORD, LPDWORD, LPLPCE_FIND_DATA);
STDAPI_(BOOL ) CeFindAllDatabases (DWORD, WORD, LPWORD, LPLPCEDB_FIND_DATA);
STDAPI_(DWORD ) CeGetLastError (void);
STDAPI_(DWORD ) CeSetFilePointer (HANDLE, LONG, PLONG, DWORD);
STDAPI_(BOOL ) CeSetEndOfFile (HANDLE);
STDAPI_(BOOL ) CeCreateDirectory (LPCWSTR, LPSECURITY_ATTRIBUTES);
STDAPI_(BOOL ) CeRemoveDirectory (LPCWSTR);
STDAPI_(BOOL ) CeCreateProcess (LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES, LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPWSTR, LPSTARTUPINFO, LPPROCESS_INFORMATION);
STDAPI_(BOOL ) CeMoveFile (LPCWSTR, LPCWSTR);
STDAPI_(BOOL ) CeCopyFile (LPCWSTR, LPCWSTR, BOOL);
STDAPI_(BOOL ) CeDeleteFile (LPCWSTR);
STDAPI_(DWORD ) CeGetFileSize (HANDLE, LPDWORD);
STDAPI_(LONG ) CeRegOpenKeyEx (HKEY, LPCWSTR, DWORD, REGSAM, PHKEY);
STDAPI_(LONG ) CeRegEnumKeyEx (HKEY, DWORD, LPWSTR, LPDWORD, LPDWORD, LPWSTR, LPDWORD, PFILETIME);
STDAPI_(LONG ) CeRegCreateKeyEx (HKEY, LPCWSTR, DWORD, LPWSTR, DWORD, REGSAM, LPSECURITY_ATTRIBUTES, PHKEY, LPDWORD);
STDAPI_(LONG ) CeRegCloseKey (HKEY);
STDAPI_(LONG ) CeRegDeleteKey (HKEY, LPCWSTR);
STDAPI_(LONG ) CeRegEnumValue (HKEY, DWORD, LPWSTR, LPDWORD, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
STDAPI_(LONG ) CeRegDeleteValue (HKEY, LPCWSTR);
STDAPI_(LONG ) CeRegQueryInfoKey (HKEY, LPWSTR, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, LPDWORD, PFILETIME);
STDAPI_(LONG ) CeRegQueryValueEx (HKEY, LPCWSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD);
STDAPI_(LONG ) CeRegSetValueEx (HKEY, LPCWSTR, DWORD, DWORD, LPBYTE, DWORD);
STDAPI_(BOOL ) CeGetStoreInformation(LPSTORE_INFORMATION);
STDAPI_(INT ) CeGetSystemMetrics (INT);
STDAPI_(INT ) CeGetDesktopDeviceCaps(INT);
STDAPI_(VOID ) CeGetSystemInfo (LPSYSTEM_INFO);
STDAPI_(DWORD ) CeSHCreateShortcut (LPWSTR, LPWSTR);
STDAPI_(BOOL ) CeSHGetShortcutTarget(LPWSTR, LPWSTR, INT);
STDAPI_(BOOL ) CeCheckPassword (LPWSTR);
STDAPI_(BOOL ) CeGetFileTime (HANDLE, LPFILETIME, LPFILETIME, LPFILETIME);
STDAPI_(BOOL ) CeSetFileTime (HANDLE, LPFILETIME, LPFILETIME, LPFILETIME);
STDAPI_(BOOL ) CeGetVersionEx (LPCEOSVERSIONINFO);
STDAPI_(HWND ) CeGetWindow (HWND, UINT);
STDAPI_(LONG ) CeGetWindowLong (HWND, int);
STDAPI_(int ) CeGetWindowText (HWND, LPWSTR, int);
STDAPI_(int ) CeGetClassName (HWND, LPWSTR, int);
STDAPI_(VOID ) CeGlobalMemoryStatus (LPMEMORYSTATUS);
STDAPI_(BOOL ) CeGetSystemPowerStatusEx(PSYSTEM_POWER_STATUS_EX, BOOL);
STDAPI_(DWORD ) CeGetTempPath (DWORD, LPWSTR);
STDAPI_(DWORD ) CeGetSpecialFolderPath(int, DWORD, LPWSTR);
STDAPI_(HANDLE) CeFindFirstDatabaseEx (PCEGUID, DWORD);
STDAPI_(CEOID ) CeFindNextDatabaseEx (HANDLE, PCEGUID);
STDAPI_(CEOID ) CeCreateDatabaseEx (PCEGUID, CEDBASEINFO*);
STDAPI_(BOOL ) CeSetDatabaseInfoEx (PCEGUID, CEOID, CEDBASEINFO*);
STDAPI_(HANDLE) CeOpenDatabaseEx (PCEGUID, PCEOID, LPWSTR, CEPROPID, DWORD, CENOTIFYREQUEST *);
STDAPI_(BOOL ) CeDeleteDatabaseEx (PCEGUID, CEOID);
STDAPI_(CEOID ) CeReadRecordPropsEx (HANDLE, DWORD, LPWORD, CEPROPID*, LPBYTE*, LPDWORD, HANDLE);
STDAPI_(CEOID ) CeWriteRecordProps (HANDLE, CEOID, WORD, CEPROPVAL*);
STDAPI_(BOOL ) CeMountDBVol (PCEGUID, LPWSTR, DWORD);
STDAPI_(BOOL ) CeUnmountDBVol (PCEGUID);
STDAPI_(BOOL ) CeFlushDBVol (PCEGUID);
STDAPI_(BOOL ) CeEnumDBVolumes (PCEGUID, LPWSTR, DWORD);
STDAPI_(BOOL ) CeOidGetInfoEx (PCEGUID, CEOID, CEOIDINFO*);
STDAPI CeSyncStart (LPCWSTR);
STDAPI CeSyncStop ();
STDAPI_(BOOL ) CeQueryInstructionSet (DWORD, LPDWORD);
STDAPI_(BOOL ) CeGetDiskFreeSpaceEx (LPCWSTR, ULARGE_INTEGER *, ULARGE_INTEGER *, ULARGE_INTEGER *);
#endif // #ifndef UNDER_CE
#ifndef NO_APIMAP
#include <ceapimap.h>
#endif
#ifdef CONN_INTERNAL
#include <prapi.h> // internal defines
#endif
#endif // #ifndef RAPI_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,445 @@
// *************************************************************************
// rapitypes.h
//
// Copyright 2002 Microsoft Corporation, All Rights Reserved
//
// Typedefs common to public and private RAPI idl.
//
// ***************************************************************************
#pragma once
#ifdef MIDL_ONLY
typedef BYTE far * LPBYTE;
#define STDAPICALLTYPE __stdcall
#endif // MIDL_ONLY
//
// The Windows CE WIN32_FIND_DATA structure differs from the
// Windows WIN32_FIND_DATA stucture so we copy the Windows CE
// definition to here so that both sides match.
//
#define MAX_PATH 260
typedef struct CE_FIND_DATA
{
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwOID;
WCHAR cFileName[MAX_PATH];
} CE_FIND_DATA;
typedef CE_FIND_DATA* LPCE_FIND_DATA;
typedef CE_FIND_DATA** LPLPCE_FIND_DATA;
//
// These are flags for CeFindAllFiles
//
#define FAF_ATTRIBUTES ((DWORD) 0x01)
#define FAF_CREATION_TIME ((DWORD) 0x02)
#define FAF_LASTACCESS_TIME ((DWORD) 0x04)
#define FAF_LASTWRITE_TIME ((DWORD) 0x08)
#define FAF_SIZE_HIGH ((DWORD) 0x10)
#define FAF_SIZE_LOW ((DWORD) 0x20)
#define FAF_OID ((DWORD) 0x40)
#define FAF_NAME ((DWORD) 0x80)
#define FAF_FLAG_COUNT ((UINT) 8)
#define FAF_ATTRIB_CHILDREN ((DWORD) 0x01000)
#define FAF_ATTRIB_NO_HIDDEN ((DWORD) 0x02000)
#define FAF_FOLDERS_ONLY ((DWORD) 0x04000)
#define FAF_NO_HIDDEN_SYS_ROMMODULES ((DWORD) 0x08000)
#define FAF_GETTARGET ((DWORD) 0x10000)
#define FAD_OID ((WORD) 0x01)
#define FAD_FLAGS ((WORD) 0x02)
#define FAD_NAME ((WORD) 0x04)
#define FAD_TYPE ((WORD) 0x08)
#define FAD_NUM_RECORDS ((WORD) 0x10)
#define FAD_NUM_SORT_ORDER ((WORD) 0x20)
#define FAD_SIZE ((WORD) 0x40)
#define FAD_LAST_MODIFIED ((WORD) 0x80)
#define FAD_SORT_SPECS ((WORD) 0x100)
#define FAD_FLAG_COUNT ((UINT) 9)
#ifndef FILE_ATTRIBUTE_INROM
#define FILE_ATTRIBUTE_INROM 0x00000040
#endif
#ifndef FILE_ATTRIBUTE_ROMSTATICREF
#define FILE_ATTRIBUTE_ROMSTATICREF 0x00001000
#endif
#ifndef FILE_ATTRIBUTE_ROMMODULE
#define FILE_ATTRIBUTE_ROMMODULE 0x00002000
#endif
//
// The following is not a standard Windows CE File Attribute.
//
#ifndef FILE_ATTRIBUTE_HAS_CHILDREN
#define FILE_ATTRIBUTE_HAS_CHILDREN 0x00010000
#endif
#ifndef FILE_ATTRIBUTE_SHORTCUT
#define FILE_ATTRIBUTE_SHORTCUT 0x00020000
#endif
typedef enum RAPISTREAMFLAG
{
STREAM_TIMEOUT_READ
} RAPISTREAMFLAG;
// forward define
#ifdef MIDL_ONLY
interface IRAPIStream;
#else
typedef struct IRAPIStream IRAPIStream;
#endif
// RAPI extension on Windows CE (e.g., MyFunctionFOO) called via CeRapiInvoke should be declared as:
// EXTERN_C RAPIEXT MyFunctionFOO;
typedef HRESULT (STDAPICALLTYPE RAPIEXT)(
DWORD cbInput, // [IN]
BYTE * pInput, // [IN]
DWORD * pcbOutput, // [OUT]
BYTE ** ppOutput, // [OUT]
IRAPIStream * pIRAPIStream // [IN]
);
//
// The following definitions are for the client side only,
// because they are already defined on Windows CE.
//
#ifndef UNDER_CE
#include <stddef.h>
typedef struct STORE_INFORMATION
{
DWORD dwStoreSize;
DWORD dwFreeSize;
} STORE_INFORMATION;
typedef STORE_INFORMATION * LPSTORE_INFORMATION;
typedef DWORD CEPROPID;
typedef CEPROPID * PCEPROPID;
#define TypeFromPropID(propid) LOWORD(propid)
typedef DWORD CEOID;
typedef CEOID *PCEOID;
typedef struct CEGUID
{
DWORD Data1;
DWORD Data2;
DWORD Data3;
DWORD Data4;
} CEGUID;
typedef CEGUID * PCEGUID;
typedef struct CENOTIFICATION {
DWORD dwSize;
DWORD dwParam;
UINT uType;
CEGUID guid;
CEOID oid;
CEOID oidParent;
} CENOTIFICATION;
#define CEDB_EXNOTIFICATION 0x00000001
typedef struct CENOTIFYREQUEST {
DWORD dwSize;
HWND hwnd;
DWORD dwFlags;
HANDLE hHeap;
DWORD dwParam;
} CENOTIFYREQUEST;
typedef CENOTIFYREQUEST * PCENOTIFYREQUEST;
typedef struct CEFILEINFO
{
DWORD dwAttributes;
CEOID oidParent;
WCHAR szFileName[MAX_PATH];
FILETIME ftLastChanged;
DWORD dwLength;
} CEFILEINFO;
typedef struct CEDIRINFO {
DWORD dwAttributes;
CEOID oidParent;
WCHAR szDirName[MAX_PATH];
} CEDIRINFO;
typedef struct CERECORDINFO {
CEOID oidParent;
} CERECORDINFO;
#define CEDB_SORT_DESCENDING 0x00000001
#define CEDB_SORT_CASEINSENSITIVE 0x00000002
#define CEDB_SORT_UNKNOWNFIRST 0x00000004
#define CEDB_SORT_GENERICORDER 0x00000008
typedef struct SORTORDERSPEC {
CEPROPID propid;
DWORD dwFlags;
} SORTORDERSPEC;
#define CEDB_MAXDBASENAMELEN 32
#define CEDB_MAXDBASENAMELEN 32
#define CEDB_MAXSORTORDER 4
#define CEDB_MAXSORTORDER 4
#define CEDB_VALIDNAME 0x0001
#define CEDB_VALIDTYPE 0x0002
#define CEDB_VALIDSORTSPEC 0x0004
#define CEDB_VALIDMODTIME 0x0008
#define CEDB_VALIDDBFLAGS 0x0010
#define CEDB_VALIDCREATE (CEDB_VALIDNAME|CEDB_VALIDTYPE|CEDB_VALIDSORTSPEC|CEDB_VALIDDBFLAGS)
#define CEDB_NOCOMPRESS 0x00010000
typedef struct CEDBASEINFO
{
DWORD dwFlags;
WCHAR szDbaseName[CEDB_MAXDBASENAMELEN];
DWORD dwDbaseType;
WORD wNumRecords;
WORD wNumSortOrder;
DWORD dwSize;
FILETIME ftLastModified;
SORTORDERSPEC rgSortSpecs[CEDB_MAXSORTORDER];
} CEDBASEINFO;
typedef struct CEDB_FIND_DATA {
CEOID OidDb;
CEDBASEINFO DbInfo;
} CEDB_FIND_DATA;
typedef CEDB_FIND_DATA * LPCEDB_FIND_DATA;
typedef CEDB_FIND_DATA ** LPLPCEDB_FIND_DATA;
#define OBJTYPE_INVALID 0
#define OBJTYPE_FILE 1
#define OBJTYPE_DIRECTORY 2
#define OBJTYPE_DATABASE 3
#define OBJTYPE_RECORD 4
typedef struct CEOIDINFO
{
WORD wObjType;
WORD wPad;
union
{
CEFILEINFO infFile;
CEDIRINFO infDirectory;
CEDBASEINFO infDatabase;
CERECORDINFO infRecord;
};
} CEOIDINFO;
#define CEDB_AUTOINCREMENT 0x00000001
#define CEDB_SEEK_CEOID 0x00000001
#define CEDB_SEEK_BEGINNING 0x00000002
#define CEDB_SEEK_END 0x00000004
#define CEDB_SEEK_CURRENT 0x00000008
#define CEDB_SEEK_VALUESMALLER 0x00000010
#define CEDB_SEEK_VALUEFIRSTEQUAL 0x00000020
#define CEDB_SEEK_VALUEGREATER 0x00000040
#define CEDB_SEEK_VALUENEXTEQUAL 0x00000080
typedef struct CEBLOB{
DWORD dwCount;
LPBYTE lpb;
} CEBLOB;
#define CEVT_I2 2
#define CEVT_UI2 18
#define CEVT_I4 3
#define CEVT_UI4 19
#define CEVT_FILETIME 64
#define CEVT_LPWSTR 31
#define CEVT_BLOB 65
#define CEVT_BOOL 11
#define CEVT_R8 5
typedef union CEVALUNION {
short iVal;
USHORT uiVal;
long lVal;
ULONG ulVal;
FILETIME filetime;
LPWSTR lpwstr;
CEBLOB blob;
BOOL boolVal;
double dblVal;
} CEVALUNION;
#define CEDB_PROPNOTFOUND 0x0100
#define CEDB_PROPDELETE 0x0200
typedef struct CEPROPVAL {
CEPROPID propid;
WORD wLenData;
WORD wFlags;
CEVALUNION val;
} CEPROPVAL;
typedef CEPROPVAL * PCEPROPVAL;
#define CEDB_MAXDATABLOCKSIZE 4092
#define CEDB_MAXPROPDATASIZE (CEDB_MAXDATABLOCKSIZE*16)
#define CEDB_MAXRECORDSIZE (128*1024)
#define CEDB_ALLOWREALLOC 0x00000001
#define CREATE_SYSTEMGUID(pguid) (memset((pguid), 0, sizeof(CEGUID)))
#define CREATE_INVALIDGUID(pguid) (memset((pguid), -1, sizeof(CEGUID)))
#define CHECK_SYSTEMGUID(pguid) !((pguid)->Data1|(pguid)->Data2|(pguid)->Data3|(pguid)->Data4)
#define CHECK_INVALIDGUID(pguid) !~((pguid)->Data1&(pguid)->Data2&(pguid)->Data3&(pguid)->Data4)
#define SYSMEM_CHANGED 0
#define SYSMEM_MUSTREBOOT 1
#define SYSMEM_REBOOTPENDING 2
#define SYSMEM_FAILED 3
typedef struct CEOSVERSIONINFO {
DWORD dwOSVersionInfoSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformId;
WCHAR szCSDVersion[ 128 ];
} CEOSVERSIONINFO;
typedef CEOSVERSIONINFO * LPCEOSVERSIONINFO;
#define AC_LINE_OFFLINE 0x00
#define AC_LINE_ONLINE 0x01
#define AC_LINE_BACKUP_POWER 0x02
#define AC_LINE_UNKNOWN 0xFF
#define BATTERY_FLAG_HIGH 0x01
#define BATTERY_FLAG_LOW 0x02
#define BATTERY_FLAG_CRITICAL 0x04
#define BATTERY_FLAG_CHARGING 0x08
#define BATTERY_FLAG_NO_BATTERY 0x80
#define BATTERY_FLAG_UNKNOWN 0xFF
#define BATTERY_PERCENTAGE_UNKNOWN 0xFF
#define BATTERY_LIFE_UNKNOWN 0xFFFFFFFF
typedef struct SYSTEM_POWER_STATUS_EX{
BYTE ACLineStatus;
BYTE BatteryFlag;
BYTE BatteryLifePercent;
BYTE Reserved1;
DWORD BatteryLifeTime;
DWORD BatteryFullLifeTime;
BYTE Reserved2;
BYTE BackupBatteryFlag;
BYTE BackupBatteryLifePercent;
BYTE Reserved3;
DWORD BackupBatteryLifeTime;
DWORD BackupBatteryFullLifeTime;
} SYSTEM_POWER_STATUS_EX;
typedef SYSTEM_POWER_STATUS_EX * PSYSTEM_POWER_STATUS_EX;
typedef SYSTEM_POWER_STATUS_EX * LPSYSTEM_POWER_STATUS_EX;
//
// MessageId: CERAPI_E_ALREADYINITIALIZED
//
// CeRapiInit(Ex) has already been successfully called
//
#define CERAPI_E_ALREADYINITIALIZED 0x80041001
typedef struct RAPIINIT
{
DWORD cbSize;
HANDLE heRapiInit;
HRESULT hrRapiInit;
} RAPIINIT;
//
// Instruction set definitions for CeQueryInstructionSet()
//
// PROCESSOR_ARCHITECTURE_x are already defined in desktop winnt.h
// Here we include the CE specific definitions from CE winnt.h
//
#define PROCESSOR_INSTRUCTION_CODE(arch, core, feature) \
((arch) << 24 | (core) << 16 | (feature))
#define PROCESSOR_X86_32BIT_CORE 1
#define PROCESSOR_MIPS16_CORE 1
#define PROCESSOR_MIPSII_CORE 2
#define PROCESSOR_MIPSIV_CORE 3
#define PROCESSOR_HITACHI_SH3_CORE 1
#define PROCESSOR_HITACHI_SH4_CORE 2
#define PROCESSOR_ARM_V4_CORE 1
#define PROCESSOR_ARM_V4I_CORE 2
#define PROCESSOR_ARM_V4T_CORE 3
#define PROCESSOR_FEATURE_NOFP 0
#define PROCESSOR_FEATURE_FP 1
#define PROCESSOR_FEATURE_DSP PROCESSOR_FEATURE_FP
#define PROCESSOR_QUERY_INSTRUCTION PROCESSOR_INSTRUCTION_CODE(0,0,0)
#define PROCESSOR_X86_32BIT_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_INTEL, PROCESSOR_X86_32BIT_CORE, PROCESSOR_FEATURE_FP)
#define PROCESSOR_MIPS_MIPS16_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_MIPS, PROCESSOR_MIPS16_CORE, PROCESSOR_FEATURE_NOFP)
#define PROCESSOR_MIPS_MIPSII_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_MIPS, PROCESSOR_MIPSII_CORE, PROCESSOR_FEATURE_NOFP)
#define PROCESSOR_MIPS_MIPSIIFP_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_MIPS, PROCESSOR_MIPSII_CORE, PROCESSOR_FEATURE_FP)
#define PROCESSOR_MIPS_MIPSIV_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_MIPS, PROCESSOR_MIPSIV_CORE, PROCESSOR_FEATURE_NOFP)
#define PROCESSOR_MIPS_MIPSIVFP_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_MIPS, PROCESSOR_MIPSIV_CORE, PROCESSOR_FEATURE_FP)
#define PROCESSOR_HITACHI_SH3_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_SHX, PROCESSOR_HITACHI_SH3_CORE, PROCESSOR_FEATURE_NOFP)
#define PROCESSOR_HITACHI_SH3DSP_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_SHX, PROCESSOR_HITACHI_SH3_CORE, PROCESSOR_FEATURE_DSP)
#define PROCESSOR_HITACHI_SH4_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_SHX, PROCESSOR_HITACHI_SH4_CORE, PROCESSOR_FEATURE_FP)
#define PROCESSOR_ARM_V4_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARM_V4_CORE, PROCESSOR_FEATURE_NOFP)
#define PROCESSOR_ARM_V4FP_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARM_V4_CORE, PROCESSOR_FEATURE_FP)
#define PROCESSOR_ARM_V4I_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARM_V4I_CORE, PROCESSOR_FEATURE_NOFP)
#define PROCESSOR_ARM_V4IFP_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARM_V4I_CORE, PROCESSOR_FEATURE_FP)
#define PROCESSOR_ARM_V4T_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARM_V4T_CORE, PROCESSOR_FEATURE_NOFP)
#define PROCESSOR_ARM_V4TFP_INSTRUCTION \
PROCESSOR_INSTRUCTION_CODE(PROCESSOR_ARCHITECTURE_ARM, PROCESSOR_ARM_V4T_CORE, PROCESSOR_FEATURE_FP)
#endif // !UNDER_CE
@@ -0,0 +1,248 @@
// ***************************************************************************
// rapitypes2.h
//
// Copyright 2003 Microsoft Corporation, All Rights Reserved
//
// Types needed for RAPI2.
//
// ***************************************************************************
#pragma once
#ifdef MIDL_ONLY
#include <basetsd.h>
typedef struct OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union UNION_OFFSET_POINTER{
struct OFFSET{
DWORD Offset;
DWORD OffsetHigh;
} OFFSET;
PVOID Pointer;
} UNION_OFFSET_POINTER;
HANDLE hEvent;
} OVERLAPPED;
typedef OVERLAPPED * LPOVERLAPPED;
#define CONST const
typedef CONST void far *LPCVOID;
typedef LONG *PLONG;
typedef struct STARTUPINFOA {
DWORD cb;
LPSTR lpReserved;
LPSTR lpDesktop;
LPSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFOA;
typedef STARTUPINFOA * LPSTARTUPINFOA;
typedef struct STARTUPINFOW {
DWORD cb;
LPWSTR lpReserved;
LPWSTR lpDesktop;
LPWSTR lpTitle;
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
WORD cbReserved2;
LPBYTE lpReserved2;
HANDLE hStdInput;
HANDLE hStdOutput;
HANDLE hStdError;
} STARTUPINFOW;
typedef STARTUPINFOW * LPSTARTUPINFOW;
#ifdef UNICODE
typedef STARTUPINFOW STARTUPINFO;
typedef LPSTARTUPINFOW LPSTARTUPINFO;
#else
typedef STARTUPINFOA STARTUPINFO;
typedef LPSTARTUPINFOA LPSTARTUPINFO;
#endif // UNICODE
typedef struct PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;
typedef PROCESS_INFORMATION * PPROCESS_INFORMATION;
typedef PROCESS_INFORMATION * LPPROCESS_INFORMATION;
typedef DWORD ACCESS_MASK;
typedef ACCESS_MASK REGSAM;
typedef HKEY *PHKEY;
typedef struct SYSTEM_INFO {
union UNION_OEMID_PROCESSOR_INFO{
DWORD dwOemId; // Obsolete field...do not use
struct PROCESSOR_INFO{
WORD wProcessorArchitecture;
WORD wReserved;
} PROCESSOR_INFO;
} UNION_OEMID_PROCESSOR_INFO;
DWORD dwPageSize;
LPVOID lpMinimumApplicationAddress;
LPVOID lpMaximumApplicationAddress;
DWORD_PTR dwActiveProcessorMask;
DWORD dwNumberOfProcessors;
DWORD dwProcessorType;
DWORD dwAllocationGranularity;
WORD wProcessorLevel;
WORD wProcessorRevision;
} SYSTEM_INFO;
typedef SYSTEM_INFO * LPSYSTEM_INFO;
typedef struct MEMORYSTATUS {
DWORD dwLength;
DWORD dwMemoryLoad;
SIZE_T dwTotalPhys;
SIZE_T dwAvailPhys;
SIZE_T dwTotalPageFile;
SIZE_T dwAvailPageFile;
SIZE_T dwTotalVirtual;
SIZE_T dwAvailVirtual;
} MEMORYSTATUS;
typedef MEMORYSTATUS * LPMEMORYSTATUS;
#define _SS_MAXSIZE 128 // Maximum size.
#define _SS_ALIGNSIZE (sizeof(__int64)) // Desired alignment.
#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short))
#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) + _SS_PAD1SIZE \
+ _SS_ALIGNSIZE))
/*
typedef struct sockaddr_storage {
short ss_family; // Address family.
char __ss_pad1[_SS_PAD1SIZE]; // 6 byte pad, this is to make
// implementation specific pad up to
// alignment field that follows explicit
// in the data structure.
__int64 __ss_align; // Field to force desired structure.
char __ss_pad2[_SS_PAD2SIZE]; // 112 byte pad to achieve desired size;
// _SS_MAXSIZE value minus size of
// ss_family, __ss_pad1, and
// __ss_align fields is 112.
} sockaddr_storage ;
typedef struct sockaddr_storage SOCKADDR_STORAGE;
*/
#endif // MIDL_ONLY
// end gross struct copy hack (everything after this is previously hacked from CE stuff that doesn't exist on desktop, so leave it as is).
//
// DEVICEID structure
//
typedef GUID RAPIDEVICEID;
#define RAPIDEVICEID_BACKCOMPAT GUID_NULL // device id for older devices
#ifndef UNDER_CE
// this is defined in CE's pwinuser.h, so we only want it for desktop
typedef struct {
DWORD dwMajor;
DWORD dwMinor;
} PLATFORMVERSION;
#endif
//
// struct to hold additional platforms and their versions.
//
#define MAX_SUB_PLATFORMS 6
typedef struct RAPI_DEVICE_PLATFORM
{
BSTR bstrName;
DWORD dwMajor;
DWORD dwMinor;
} RAPI_DEVICE_PLATFORM;
//
// RAPI_DEVICEINFO
//
typedef struct RAPI_DEVICEINFO
{
RAPIDEVICEID DeviceId;
DWORD dwOsVersionMajor;
DWORD dwOsVersionMinor;
BSTR bstrName;
BSTR bstrPlatform;
} RAPI_DEVICEINFO;
#define FreeDeviceInfoData(pDevInfo) \
do \
{ \
SysFreeString((pDevInfo)->bstrName); \
SysFreeString((pDevInfo)->bstrPlatform); \
} while (0,0)
#ifndef MIDL_ONLY
#include "winsock2.h"
#endif
//
// RAPI_DEVICESTATUS
//
typedef enum RAPI_DEVICESTATUS
{
RAPI_DEVICE_DISCONNECTED = 0,
RAPI_DEVICE_CONNECTED = 1,
} RAPI_DEVICESTATUS;
//
// op codes for IRAPIDesktop funcs
//
typedef enum RAPI_GETDEVICEOPCODE
{
RAPI_GETDEVICE_NONBLOCKING,
RAPI_GETDEVICE_BLOCKING
} RAPI_GETDEVICEOPCODE;
//
// Connected type codes
//
typedef enum RAPI_CONNECTIONTYPE
{
RAPI_CONNECTION_USB = 0,
RAPI_CONNECTION_IR = 1,
RAPI_CONNECTION_SERIAL = 2,
RAPI_CONNECTION_NETWORK = 3,
} RAPI_CONNECTIONTYPE;
typedef struct RAPI_CONNECTIONINFO {
SOCKADDR_STORAGE ipaddr;
SOCKADDR_STORAGE hostIpaddr;
RAPI_CONNECTIONTYPE connectionType;
} RAPI_CONNECTIONINFO;
@@ -0,0 +1,220 @@
//#define PLUGIN_NAME "Nullsoft ActiveSync Plug-in"
#define PLUGIN_VERSION L"0.25"
#include "ASDevice.h"
int init();
void quit();
intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3);
extern PMPDevicePlugin plugin = {PMPHDR_VER,0,init,quit,MessageProc};
static HANDLE killEvent=0, hThread=0;
static DWORD WINAPI ThreadFunc(LPVOID lpParam);
IRAPIDesktop *pIRapiDesktop = NULL;
// wasabi based services for localisation support
api_language *WASABI_API_LNG = 0;
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
std::vector<ASDevice*> devices;
std::vector<ejectedDevice*> ejected;
static RAPIDEVICEID lastDevId;
class MyRAPISink : public IRAPISink {
public:
virtual HRESULT STDMETHODCALLTYPE OnDeviceConnected(IRAPIDevice *pIDevice) {
RAPI_DEVICEINFO devInfo;
if(!SUCCEEDED(pIDevice->GetDeviceInfo(&devInfo))) return S_OK;
SysFreeString(devInfo.bstrName);
SysFreeString(devInfo.bstrPlatform);
EnterCriticalSection(&cs);
lastDevId = devInfo.DeviceId;
for(unsigned int i=0; i<ejected.size(); i++) {
if(devInfo.DeviceId == ejected[i]->id) {
ejected[i]->marked=true;
LeaveCriticalSection(&cs);
return S_OK;
}
}
for(unsigned int i=0; i<devices.size(); i++) {
if(devInfo.DeviceId == devices[i]->devInfo.DeviceId || devices[i]->pIDevice == pIDevice) {
LeaveCriticalSection(&cs);
return S_OK;
}
}
IRAPISession *pISession = NULL;
if (SUCCEEDED(pIDevice->CreateSession(&pISession))) {
if (SUCCEEDED(pISession->CeRapiInit())) devices.push_back(new ASDevice(pIDevice,pISession));
else pISession->Release();
}
LeaveCriticalSection(&cs);
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE OnDeviceDisconnected(IRAPIDevice *pIDevice) {
EnterCriticalSection(&cs);
RAPI_DEVICEINFO devInfo;
if(!SUCCEEDED(pIDevice->GetDeviceInfo(&devInfo))) return S_OK;
for(unsigned int i=0; i<devices.size(); i++) {
if(devInfo.DeviceId == devices[i]->devInfo.DeviceId || devices[i]->pIDevice == pIDevice) {
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)devices[i],PMP_IPC_DEVICEDISCONNECTED);
delete devices[i];
}
}
SysFreeString(devInfo.bstrName);
SysFreeString(devInfo.bstrPlatform);
LeaveCriticalSection(&cs);
return S_OK;
}
DWORD RAPISinkContext;
CRITICAL_SECTION cs;
ULONG refs;
MyRAPISink() {refs=1; InitializeCriticalSection(&cs);}
~MyRAPISink() { DeleteCriticalSection(&cs); }
#define IMPLEMENTS(ifc) if (riid == IID_ ## ifc) { ++refs; *ppvObject = static_cast<ifc *>(this); return S_OK; }
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,void __RPC_FAR *__RPC_FAR *ppvObject) {
IMPLEMENTS(IRAPISink);
IMPLEMENTS(IUnknown);
*ppvObject = NULL;
return E_NOINTERFACE;
}
virtual ULONG STDMETHODCALLTYPE AddRef() { return ++refs; }
virtual ULONG STDMETHODCALLTYPE Release() { int x = --refs; if(!x) delete this; return x; }
#undef IMPLEMENTS
};
MyRAPISink *pMyRapiSink=NULL;
int init() {
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HRESULT hr = CoCreateInstance(CLSID_RAPI,NULL,CLSCTX_INPROC_SERVER,IID_IRAPIDesktop,(void**)&pIRapiDesktop);
if(!SUCCEEDED(hr) || !pIRapiDesktop) return -1; // no activesync on this computer!
// loader so that we can get the localisation service api for use
waServiceFactory *sf = plugin.service->service_getServiceByGuid(languageApiGUID);
if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
// need to have this initialised before we try to do anything with localisation features
WASABI_API_START_LANG(plugin.hDllInstance,PmpACTIVESYNCLangGUID);
static wchar_t szDescription[256];
swprintf(szDescription, ARRAYSIZE(szDescription),
WASABI_API_LNGSTRINGW(IDS_NULLSOFT_ACTIVESYNC_PLUGIN), PLUGIN_VERSION);
plugin.description = szDescription;
killEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
DWORD dwThreadId;
hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &dwThreadId);
return 0;
}
static void enumDevices() {
// find all the currently connected devices
IRAPIEnumDevices* pIRapiEnumDevices = NULL;
HRESULT hr = pIRapiDesktop->EnumDevices(&pIRapiEnumDevices);
for (unsigned int i = 0; i < ejected.size(); i++) ejected[i]->marked = false;
while (SUCCEEDED(hr) && pIRapiEnumDevices) {
IRAPIDevice* pIRapiDevice = NULL;
hr = pIRapiEnumDevices->Next(&pIRapiDevice);
if (SUCCEEDED(hr) && pIRapiDevice) {
pMyRapiSink->OnDeviceConnected(pIRapiDevice);
pIRapiDevice->Release();
}
else {
pIRapiEnumDevices->Release();
pIRapiEnumDevices = NULL;
}
}
//for (unsigned int i = 0; i < ejected.size(); i++)
//{
// if (!ejected[i]->marked)
// {
// free(ejected[i]);
// ejected.eraseindex(i);
// }
//}
auto it = ejected.begin();
while (it != ejected.end())
{
ejectedDevice* dev = *it;
if (!dev->marked)
{
free(dev);
it = ejected.erase(it);
}
else
{
it++;
}
}
}
static void init2() {
// set up device connection/disconnection notifications
pMyRapiSink = new MyRAPISink();
pIRapiDesktop->Advise(pMyRapiSink,(DWORD_PTR*)&pMyRapiSink->RAPISinkContext);
// find currently attached devices
enumDevices();
}
void quit() {
SetEvent(killEvent);
if (hThread) {
for(;;) {
int val = WaitForSingleObjectEx(hThread,15000,TRUE);
if(val == WAIT_OBJECT_0) { CloseHandle(hThread); break; }
else if(val == WAIT_TIMEOUT) { TerminateThread(hThread, 0); break; }
else continue;
}
}
CloseHandle(killEvent);
pIRapiDesktop->UnAdvise(pMyRapiSink->RAPISinkContext);
pIRapiDesktop->Release();
pMyRapiSink->Release();
CoUninitialize();
for(unsigned int i=0; i<ejected.size(); i++) free(ejected[i]);
}
static DWORD WINAPI ThreadFunc(LPVOID lpParam) {
CoInitializeEx(0,COINIT_MULTITHREADED);
init2();
while (WaitForSingleObjectEx(killEvent,5000,TRUE) != WAIT_OBJECT_0) {
// FUCKO: For some reason I'm not getting the device connected notifications, so lets just enum for devices on a regular basis.
enumDevices();
}
CoUninitialize();
return 0;
}
intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3) {
if (msg == PMP_NO_CONFIG)
return TRUE;
return FALSE;
}
extern "C" {
__declspec( dllexport ) PMPDevicePlugin * winampGetPMPDevicePlugin(){return &plugin;}
__declspec( dllexport ) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg, int param) {
int i = (int)devices.size();
while(i-- > 0) devices[i]->Close();
return PMP_PLUGIN_UNINSTALL_NOW;
}
};
@@ -0,0 +1,116 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// RCDATA
//
IDR_ACTIVESYNC_ICON RCDATA ".\\resources\\activeSyncIcon.png"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_CONFIG DIALOGEX 0, 0, 264, 226
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Folders",IDC_STATIC,4,3,255,83
LTEXT "Music Folder",IDC_STATIC,8,16,40,8
EDITTEXT IDC_FOLDER_MUSIC,56,14,197,14,ES_AUTOHSCROLL
LTEXT "Video Folder",IDC_STATIC,8,32,40,8
EDITTEXT IDC_FOLDER_VIDEO,56,30,197,14,ES_AUTOHSCROLL
LTEXT "Playlist Folder",IDC_STATIC,8,49,45,8
EDITTEXT IDC_FOLDER_PLAYLIST,56,46,197,14,ES_AUTOHSCROLL
PUSHBUTTON "Rescan folders",IDC_RESCAN,7,66,56,14
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_NULLSOFT_ACTIVESYNC_PLUGIN "Nullsoft ActiveSync Plug-in v%s"
65535 "{B81F32B8-4AA4-4eba-8798-95F13812F638}"
END
STRINGTABLE
BEGIN
IDS_LOADING "Loading %s..."
IDS_TRANSFERRING "Transferring..."
IDS_CANNOT_OPEN_LOCAL_FILE "Cannot open local file"
IDS_CANNOT_OPEN_FILE_ON_DEVICE "Cannot open file on device"
IDS_ERROR_WRITING_FILE "Error writing to file"
IDS_TRANSFERRING_PERCENT "Transferring %d%%"
IDS_DONE "Done"
IDS_CANNOT_OPEN_DESTINATION "Cannot open destination file"
IDS_ADVANCED "Advanced"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
@@ -0,0 +1,18 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pmp_activesync", "pmp_activesync.vcproj", "{60D71BB7-D741-444E-99ED-7249A716B99F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{60D71BB7-D741-444E-99ED-7249A716B99F}.Debug|Win32.ActiveCfg = Debug|Win32
{60D71BB7-D741-444E-99ED-7249A716B99F}.Release|Win32.ActiveCfg = Release|Win32
{60D71BB7-D741-444E-99ED-7249A716B99F}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,357 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{60D71BB7-D741-444E-99ED-7249A716B99F}</ProjectGuid>
<RootNamespace>pmp_activesync</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>17.0.32505.173</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<GenerateManifest>true</GenerateManifest>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnabled>false</VcpkgEnabled>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>$(IntDir)$(TargetName).tlb</TypeLibraryName>
<HeaderFileName />
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\replicant;activesync\Inc;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WINDOWS;_USRDLL;ML_ex_EXPORTS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>rapiuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>activesync\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<GenerateMapFile>false</GenerateMapFile>
<MapExports>false</MapExports>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention />
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<IgnoreSpecificDefaultLibraries>libc.lib;msvcprt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)*.dll ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)*.pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TypeLibraryName>$(IntDir)$(TargetName).tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\replicant;activesync\Inc;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WINDOWS;_USRDLL;ML_ex_EXPORTS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
</PrecompiledHeader>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>rapiuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>activesync\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<GenerateMapFile>false</GenerateMapFile>
<MapExports>false</MapExports>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<IgnoreSpecificDefaultLibraries>libc.lib;msvcprt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)*.dll ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)*.pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>$(IntDir)$(TargetName).tlb</TypeLibraryName>
<HeaderFileName />
</Midl>
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\replicant;activesync\Inc;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WINDOWS;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<PrecompiledHeader />
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>rapiuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>activesync\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>libc.lib;msvcprt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
<TypeLibraryName>$(IntDir)$(TargetName).tlb</TypeLibraryName>
<HeaderFileName>
</HeaderFileName>
</Midl>
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\replicant;activesync\Inc;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WINDOWS;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<PrecompiledHeader>
</PrecompiledHeader>
<PrecompiledHeaderOutputFile>$(IntDir)$(TargetName).pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>rapiuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>activesync\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>libc.lib;msvcprt.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp" />
<ClCompile Include="ASDevice.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\General\gen_ml\ml.h" />
<ClInclude Include="..\..\Library\ml_pmp\pmp.h" />
<ClInclude Include="ASDevice.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<Image Include="resources\activeSyncIcon.png" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_activesync.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{b35076f0-5e1b-4df9-baa4-ef63b5b1e046}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{5ed7e868-d2e1-4274-890e-0f94583196e2}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl</Extensions>
</Filter>
<Filter Include="resources">
<UniqueIdentifier>{194593b8-f700-465e-aa6d-b982a8271c7e}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ASDevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ASDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\General\gen_ml\ml.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\Library\ml_pmp\pmp.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="resources\activeSyncIcon.png">
<Filter>resources</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_activesync.rc">
<Filter>resources</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
@@ -0,0 +1,31 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by pmp_activesync.rc
//
#define IDS_LOADING 1
#define IDS_TRANSFERRING 2
#define IDS_CANNOT_OPEN_LOCAL_FILE 3
#define IDS_CANNOT_OPEN_FILE_ON_DEVICE 4
#define IDS_ERROR_WRITING_FILE 5
#define IDS_TRANSFERRING_PERCENT 6
#define IDS_DONE 7
#define IDS_CANNOT_OPEN_DESTINATION 8
#define IDS_ADVANCED 9
#define IDR_ACTIVESYNC_ICON 101
#define IDD_CONFIG 102
#define IDC_FOLDER_MUSIC 1001
#define IDC_FOLDER_PLAYLIST 1002
#define IDC_FOLDER_VIDEO 1003
#define IDC_RESCAN 1004
#define IDS_NULLSOFT_ACTIVESYNC_PLUGIN 65534
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 106
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1005
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 246 B

@@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../../../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,25,0,0
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp Portable Device Plug-in"
VALUE "FileVersion", "0,25,0,0"
VALUE "InternalName", "Nullsoft ActiveSync"
VALUE "LegalCopyright", "Copyright © 2006-2023 Winamp SA"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "pmp_activesync.dll"
VALUE "ProductName", "Winamp"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
@@ -0,0 +1,58 @@
#include "../../Library/ml_pmp/pmp.h"
#include "api.h"
#include "../agave/albumart/svc_albumartprovider.h"
#include <api/service/waservicefactory.h>
extern PMPDevicePlugin plugin;
static svc_albumArtProvider *FindProvider(const wchar_t *filename, int providerType, waServiceFactory **factory)
{
FOURCC albumartprovider = svc_albumArtProvider::getServiceType();
int n = (int)plugin.service->service_getNumServices(albumartprovider);
for (int i=0; i<n; i++)
{
waServiceFactory *sf = plugin.service->service_enumService(albumartprovider,i);
if (sf)
{
svc_albumArtProvider * provider = (svc_albumArtProvider*)sf->getInterface();
if (provider)
{
if (provider->ProviderType() == providerType && provider->IsMine(filename))
{
*factory = sf;
return provider;
}
sf->releaseInterface(provider);
}
}
}
return NULL;
}
void CopyAlbumArt(const wchar_t *source, const wchar_t *destination)
{
size_t datalen = 0;
void *data = 0;
wchar_t *mimeType = 0;
waServiceFactory *destinationFactory = 0;
svc_albumArtProvider *destinationProvider = FindProvider(destination, ALBUMARTPROVIDER_TYPE_EMBEDDED, &destinationFactory);
if (destinationFactory)
{
/* First, look to see if there's already embedded album art */
if (destinationProvider->GetAlbumArtData(destination, L"cover", &data, &datalen, &mimeType) == ALBUMARTPROVIDER_SUCCESS && data && datalen)
{
destinationFactory->releaseInterface(destinationProvider);
WASABI_API_MEMMGR->sysFree(data);
WASABI_API_MEMMGR->sysFree(mimeType);
return;
}
else if (AGAVE_API_ALBUMART->GetAlbumArtData(source, L"cover", &data, &datalen, &mimeType) == ALBUMART_SUCCESS && data && datalen)
{
destinationProvider->SetAlbumArtData(destination, L"cover", data, datalen, mimeType);
WASABI_API_MEMMGR->sysFree(data);
WASABI_API_MEMMGR->sysFree(mimeType);
destinationFactory->releaseInterface(destinationProvider);
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,240 @@
#pragma once
#include <windows.h>
#include <Dbt.h>
#include "../../Library/ml_pmp/transcoder.h"
#include "../../Library/ml_pmp/pmp.h"
#include "../nde/nde_c.h"
#include "../nu/AutoLock.h"
#include <vector>
#define WINAMP_ANDROID_MARKER_FILE L"\\.winamp\\winamp.info"
//Filename="E:\Howling Bells - Into The Chaos.MP3"
//Artist="Howling Bells"
//Album="E:"
//Title="Into The Chaos"
//Genre=""
//AlbumArtist=""
//Publisher=""
//Composer=""
//Year="0"
//Track="0"
//Bitrate="0"
//Playcount="0"
//Discnum="0"
//Length="0"
//Size="7767879"
enum
{
NDE_ANDROID_FAILURE=0,
NDE_ANDROID_SUCCESS=1,
};
enum
{
DEVICEVIEW_COL_FILENAME = 0,
DEVICEVIEW_COL_ARTIST=1,
DEVICEVIEW_COL_ALBUM=2,
DEVICEVIEW_COL_TITLE=3,
DEVICEVIEW_COL_GENRE=4,
DEVICEVIEW_COL_ALBUM_ARTIST=5,
DEVICEVIEW_COL_PUBLISHER=6,
DEVICEVIEW_COL_COMPOSER=7,
DEVICEVIEW_COL_YEAR=8,
DEVICEVIEW_COL_TRACK=9,
DEVICEVIEW_COL_BITRATE=10,
DEVICEVIEW_COL_DISC_NUMBER=11,
DEVICEVIEW_COL_LENGTH=12,
DEVICEVIEW_COL_SIZE=13,
DEVICEVIEW_COL_PLAY_COUNT=14,
};
#define TAG_CACHE L"winamp_metadata.dat"
#define FIELD_LENGTH 1024
class AndroidSong {
public:
AndroidSong();
wchar_t filename[MAX_PATH];
wchar_t artist[FIELD_LENGTH];
wchar_t album[FIELD_LENGTH];
wchar_t title[FIELD_LENGTH];
wchar_t genre[FIELD_LENGTH];
wchar_t albumartist[FIELD_LENGTH];
wchar_t publisher[FIELD_LENGTH];
wchar_t composer[FIELD_LENGTH];
int year,track,length,discnum,bitrate,playcount;
__int64 size;
BOOL filled;
wchar_t ext[ 6 ];
};
enum DeviceType {
TYPE_OTHER,
TYPE_PSP,
};
class AndroidPlaylist;
class AndroidArt
{
public:
AndroidArt(ARGB32 *bits, int w, int h);
~AndroidArt();
ARGB32 *bits;
int w,h;
};
class AndroidDevice : public Device
{
public:
AndroidDevice(wchar_t drive, pmpDeviceLoading * load);
~AndroidDevice();
AndroidDevice();
void fileProbe(wchar_t * indir);
void tag(void); //load ID3 tags from cache or mp3 file
void createDeviceFields();
int openDeviceDatabase();
int openDeviceTable();
void closeDeviceTable();
static void CloseDatabase();
void SeekToBegininngOfDevice(nde_scanner_t s);
void refreshNDECache(void);
void fillMetaData(AndroidSong *s);
static int getFileInfoW(const wchar_t *filename, const wchar_t *metadata, wchar_t *dest, size_t len);
void setupTranscoder();
AndroidPlaylist* getMasterPlaylist();
AndroidSong* findSongInMasterPlaylist(const wchar_t *songfn);
void writeRecordToDB(AndroidSong* songToPrint);
//////////////////////////////////////////
virtual __int64 getDeviceCapacityAvailable(); // in bytes
virtual __int64 getDeviceCapacityTotal(); // in bytes
virtual void Eject(); // if you ejected successfully, you MUST call PMP_IPC_DEVICEDISCONNECTED and delete this;
virtual void Close(); // save any changes, and call PMP_IPC_DEVICEDISCONNECTED AND delete this;
// return 0 for success, -1 for failed or cancelled
virtual int transferTrackToDevice(const itemRecordW * track, // the track to transfer
void * callbackContext, //pass this to the callback
void (*callback)(void *callbackContext, wchar_t *status), // call this every so often so the GUI can be updated. Including when finished!
songid_t * songid, // fill in the songid when you are finished
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
);
virtual int trackAddedToTransferQueue(const itemRecordW *track); // return 0 to accept, -1 for "not enough space", -2 for "incorrect format"
virtual void trackRemovedFromTransferQueue(const itemRecordW *track);
// return the amount of space that will be taken up on the device by the track (once it has been tranferred)
// or 0 for incompatable. This is usually the filesize, unless you are transcoding. An estimate is acceptable.
virtual __int64 getTrackSizeOnDevice(const itemRecordW *track);
virtual void deleteTrack(songid_t songid); // physically remove from device. Be sure to remove it from all the playlists!
virtual void commitChanges(); // optional. Will be called at a good time to save changes
virtual int getPlaylistCount(); // always at least 1. playlistnumber 0 is the Master Playlist containing all tracks.
// PlaylistName(0) should return the name of the device.
virtual void getPlaylistName(int playlistnumber, wchar_t *buf, int len);
virtual int getPlaylistLength(int playlistnumber);
virtual songid_t getPlaylistTrack(int playlistnumber,int songnum); // returns a songid
virtual void setPlaylistName(int playlistnumber, const wchar_t *buf); // with playlistnumber==0, set the name of the device.
virtual void playlistSwapItems(int playlistnumber, int posA, int posB); // swap the songs at position posA and posB
virtual void sortPlaylist(int playlistnumber, int sortBy);
virtual void addTrackToPlaylist(int playlistnumber, songid_t songid); // adds songid to the end of the playlist
virtual void removeTrackFromPlaylist(int playlistnumber, int songnum); //where songnum is the position of the track in the playlist
virtual void deletePlaylist(int playlistnumber);
virtual int newPlaylist(const wchar_t *name); // create empty playlist, returns playlistnumber. -1 for failed.
virtual void getTrackArtist(songid_t songid, wchar_t *buf, int len);
virtual void getTrackAlbum(songid_t songid, wchar_t *buf, int len);
virtual void getTrackTitle(songid_t songid, wchar_t *buf, int len);
virtual int getTrackTrackNum(songid_t songid);
virtual int getTrackDiscNum(songid_t songid);
virtual void getTrackGenre(songid_t songid, wchar_t * buf, int len);
virtual int getTrackYear(songid_t songid);
virtual __int64 getTrackSize(songid_t songid); // in bytes
virtual int getTrackLength(songid_t songid); // in millisecs
virtual int getTrackBitrate(songid_t songid); // in kbps
virtual int getTrackPlayCount(songid_t songid);
virtual int getTrackRating(songid_t songid); //0-5
virtual __time64_t getTrackLastPlayed(songid_t songid); // in unix time format
virtual __time64_t getTrackLastUpdated(songid_t songid); // in unix time format
virtual void getTrackAlbumArtist(songid_t songid, wchar_t *buf, int len);
virtual void getTrackPublisher(songid_t songid, wchar_t *buf, int len);
virtual void getTrackComposer(songid_t songid, wchar_t *buf, int len);
virtual int getTrackType(songid_t songid);
virtual void getTrackExtraInfo(songid_t songid, const wchar_t *field, wchar_t *buf, int len) ; //optional
// feel free to ignore any you don't support
virtual void setTrackArtist(songid_t songid, const wchar_t *value);
virtual void setTrackAlbum(songid_t songid, const wchar_t *value);
virtual void setTrackTitle(songid_t songid, const wchar_t *value);
virtual void setTrackTrackNum(songid_t songid, int value);
virtual void setTrackDiscNum(songid_t songid, int value);
virtual void setTrackGenre(songid_t songid, const wchar_t *value);
virtual void setTrackYear(songid_t songid, int year);
virtual void setTrackPlayCount(songid_t songid, int value);
virtual void setTrackRating(songid_t songid, int value);
virtual void setTrackLastPlayed(songid_t songid, __time64_t value); // in unix time format
virtual void setTrackLastUpdated(songid_t songid, __time64_t value); // in unix time format
virtual void setTrackAlbumArtist(songid_t songid, const wchar_t *value);
virtual void setTrackPublisher(songid_t songid, const wchar_t *value);
virtual void setTrackComposer(songid_t songid, const wchar_t *value);
virtual void setTrackExtraInfo(songid_t songid, const wchar_t *field, const wchar_t *value) ; //optional
virtual bool playTracks(songid_t * songidList, int listLength, int startPlaybackAt, bool enqueue); // return false if unsupported
virtual intptr_t extraActions(intptr_t param1, intptr_t param2, intptr_t param3,intptr_t param4);
virtual bool copyToHardDriveSupported();
virtual __int64 songSizeOnHardDrive(songid_t song); // how big a song will be when copied back. Return -1 for not supported.
virtual int copyToHardDrive(songid_t song, // the song to copy
wchar_t * path, // path to copy to, in the form "c:\directory\song". The directory will already be created, you must append ".mp3" or whatever to this string! (there is space for at least 10 new characters).
void * callbackContext, //pass this to the callback
void (*callback)(void * callbackContext, wchar_t * status), // call this every so often so the GUI can be updated. Including when finished!
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
); // -1 for failed/not supported. 0 for success.
// art functions
virtual void setArt(songid_t songid, void *buf, int w, int h); //buf is in format ARGB32*
virtual pmpart_t getArt(songid_t songid);
virtual void releaseArt(pmpart_t art);
virtual int drawArt(pmpart_t art, HDC dc, int x, int y, int w, int h);
virtual void getArtNaturalSize(pmpart_t art, int *w, int *h);
virtual void setArtNaturalSize(pmpart_t art, int w, int h);
virtual void getArtData(pmpart_t art, void* data); // data ARGB32* is at natural size
virtual bool artIsEqual(pmpart_t a, pmpart_t b);
// Additional attributes
Transcoder *transcoder;
wchar_t drive;
wchar_t iniFile[MAX_PATH];
wchar_t pldir[MAX_PATH];
wchar_t songFormat[MAX_PATH];
wchar_t supportedFormats[MAX_PATH];
wchar_t purgeFolders[2];
int pl_write_mode; // used to determine how the playlists are stored
__int64 transferQueueLength;
std::vector<AndroidPlaylist*> androidPlaylists;
bool loadedUpToDate; //whether or not songs in memory are tagged and correct
static nde_database_t discDB;
nde_table_t deviceTable;
Nullsoft::Utility::LockGuard dbcs;
wchar_t ndeDataFile[100];
wchar_t ndeIndexFile[100];
private:
// update a track with new metadata (string)
void updateTrackField(AndroidSong* song, unsigned int col, const void* newValue, int fieldType);
bool readRecordFromDB(AndroidSong* song);
bool songChanged(AndroidSong* song);
};
@@ -0,0 +1,134 @@
#include "./androiddevice.h"
#include "./AndroidPlaylist.h"
#include <shlwapi.h>
#include <strsafe.h>
// dtor
// cleanup the memory allocated for the vector of songs
AndroidPlaylist::~AndroidPlaylist()
{
}
// this is the constructor that gets called
AndroidPlaylist::AndroidPlaylist(AndroidDevice& d, LPCTSTR fileName, BOOL m)
: device(d), master(m), dirty(false)
{
StringCbCopyW(filename, sizeof(filename), fileName);
StringCbCopyW(playlistName, sizeof(playlistName), PathFindFileName(fileName));
StringCbCopyW(playlistPath, sizeof(playlistName), fileName);
PathRemoveFileSpec(playlistPath);
}
void AndroidPlaylist::OnFile( const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info )
{
if ( filename == NULL )
return;
AndroidSong *song = NULL;
//Nullsoft::Utility::AutoLock songs_lock(songs_guard);
song = device.findSongInMasterPlaylist( filename );
songs.push_back( song );
}
size_t AndroidPlaylist::size()
{
//Nullsoft::Utility::AutoLock songs_lock(songs_guard);
return songs.size();
}
AndroidSong *&AndroidPlaylist::at(size_t index)
{
//Nullsoft::Utility::AutoLock songs_lock(songs_guard);
return songs.at(index);
}
void AndroidPlaylist::push_back(AndroidSong *callback)
{
//Nullsoft::Utility::AutoLock songs_lock(songs_guard);
songs.push_back(callback);
dirty=TRUE;
}
void AndroidPlaylist::RemoveSong(AndroidSong *song)
{
//Nullsoft::Utility::AutoLock songs_lock(songs_guard);
size_t old_size = songs.size();
//songs.eraseAll(song);
auto it = songs.begin();
while (it != songs.end())
{
if (*it != song)
{
it++;
continue;
}
it = songs.erase(it);
}
if (old_size != songs.size())
dirty=TRUE;
}
void AndroidPlaylist::swap(size_t index1, size_t index2)
{
//Nullsoft::Utility::AutoLock songs_lock(songs_guard);
AndroidSong *temp = songs[index1];
songs[index1] = songs[index2];
songs[index2] = temp;
dirty = true;
}
void AndroidPlaylist::eraseAt(size_t index)
{
// Nullsoft::Utility::AutoLock songs_lock(songs_guard);
songs.erase(songs.begin() + index);
dirty=true;
}
static int filenamecmp( const wchar_t *f1, const wchar_t *f2 )
{
for ( ;;)
{
wchar_t c1 = *f1++;
wchar_t c2 = *f2++;
if ( !c1 && !c2 )
return 0;
if ( !c1 )
return -1;
if ( !c2 )
return 1;
c1 = towupper( c1 );
c2 = towupper( c2 );
if ( c1 == '\\' )
c1 = '/';
if ( c2 == '\\' )
c2 = '/';
if ( c1 < c2 )
return -1;
else if ( c1 > c2 )
return 1;
}
}
AndroidSong *AndroidPlaylist::FindSong(const wchar_t *filename)
{
//Nullsoft::Utility::AutoLock songs_lock(songs_guard);
for (SongList::iterator e = songs.begin(); e != songs.end(); e++)
{
if (filenamecmp(filename, (*e)->filename) == 0)
{
return (*e);
}
}
return 0;
}
#define CBCLASS AndroidPlaylist
START_DISPATCH;
VCB(IFC_PLAYLISTLOADERCALLBACK_ONFILE, OnFile)
END_DISPATCH;
@@ -0,0 +1,49 @@
#pragma once
#include <vector>
#include "../playlist/ifc_playlistloadercallback.h"
#include "../nu/AutoLock.h"
class AndroidDevice;
class AndroidSong;
class AndroidPlaylist: public ifc_playlistloadercallback
{
public:
AndroidPlaylist(AndroidDevice& d, LPCTSTR pszPlaylist, BOOL master);
~AndroidPlaylist();
public:
/*** ifc_playlistloadercallback ***/
void OnFile(const wchar_t *filename, const wchar_t *title, int lengthInMS, ifc_plentryinfo *info);
public:
// utility
BOOL isMaster() { return master; }
wchar_t* getFilename() { return filename; }
size_t size();
AndroidSong *&at(size_t index);
void push_back(AndroidSong *callback);
void RemoveSong(AndroidSong *song);
void swap(size_t index1, size_t index2);
void eraseAt(size_t index);
AndroidSong *FindSong(const wchar_t *filename);
protected:
RECVS_DISPATCH;
private:
AndroidDevice &device;
typedef std::vector<AndroidSong*> SongList;
SongList songs;
public:
//Nullsoft::Utility::LockGuard songs_guard;
wchar_t playlistName[MAX_PATH];
wchar_t playlistPath[MAX_PATH];
wchar_t filename[MAX_PATH];
BOOL master;
BOOL dirty;
};
@@ -0,0 +1,74 @@
#include "./androidplaylistsaver.h"
#include "./androidplaylist.h"
#include "./androiddevice.h"
#include "./api.h"
#include <strsafe.h>
AndroidPlaylistSaver::AndroidPlaylistSaver(LPCTSTR iFilename, LPCTSTR iPlaylistName, AndroidPlaylist *iPlaylist)
: filename((LPTSTR)iFilename), title((LPTSTR)iPlaylistName), playlist(iPlaylist)
{
}
AndroidPlaylistSaver::~AndroidPlaylistSaver()
{
}
HRESULT AndroidPlaylistSaver::Save()
{
INT result = WASABI_API_PLAYLISTMNGR->Save(filename, this);
return (PLAYLISTMANAGER_SUCCESS == result) ? S_OK : E_FAIL;
}
size_t AndroidPlaylistSaver::GetNumItems()
{
return playlist->size();
}
size_t AndroidPlaylistSaver::GetItem(size_t item, wchar_t *filename, size_t filenameCch)
{
AndroidSong* song = (AndroidSong *) playlist->at(item);
if (!song) return 0;
HRESULT hr = StringCchCopyEx(filename, filenameCch, song->filename, NULL, NULL, STRSAFE_IGNORE_NULLS);
if (FAILED(hr))
*filename = L'\0';
return SUCCEEDED(hr);
}
size_t AndroidPlaylistSaver::GetItemTitle(size_t item, wchar_t *title, size_t titleCch)
{
AndroidSong* song = (AndroidSong *) playlist->at(item);
if (!song) return 0;
HRESULT hr = StringCchCopyEx(title, titleCch, song->title, NULL, NULL, STRSAFE_IGNORE_NULLS);
if (FAILED(hr))
*title = L'\0';
return SUCCEEDED(hr);
}
int AndroidPlaylistSaver::GetItemLengthMs(size_t item)
{
AndroidSong* song = (AndroidSong *) playlist->at(item);
if (!song) return 0;
return song->length ? song->length: -1;
}
size_t AndroidPlaylistSaver::GetItemExtendedInfo(size_t item, const wchar_t *metadata, wchar_t *info, size_t infoCch)
{
return 0;
}
#define CBCLASS AndroidPlaylistSaver
START_DISPATCH;
CB(IFC_PLAYLIST_GETNUMITEMS, GetNumItems)
CB(IFC_PLAYLIST_GETITEM, GetItem)
CB(IFC_PLAYLIST_GETITEMTITLE, GetItemTitle)
CB(IFC_PLAYLIST_GETITEMLENGTHMILLISECONDS, GetItemLengthMs)
CB(IFC_PLAYLIST_GETITEMEXTENDEDINFO, GetItemExtendedInfo)
END_DISPATCH;
@@ -0,0 +1,33 @@
#pragma once
#include <wtypes.h>
#include "../playlist/ifc_playlist.h"
class AndroidPlaylist;
class AndroidPlaylistSaver : public ifc_playlist
{
public:
AndroidPlaylistSaver(LPCTSTR iFilename, LPCTSTR iTitle, AndroidPlaylist * iPlaylist);
virtual ~AndroidPlaylistSaver();
public:
/*** ifc_playlist ***/
size_t GetNumItems();
size_t GetItem(size_t item, wchar_t *filename, size_t filenameCch);
size_t GetItemTitle(size_t item, wchar_t *title, size_t titleCch);
int GetItemLengthMs(size_t item); // TODO: maybe microsecond for better resolution?
size_t GetItemExtendedInfo(size_t item, const wchar_t *metadata, wchar_t *info, size_t infoCch);
HRESULT Save();
protected:
RECVS_DISPATCH;
protected:
LPTSTR title;
LPTSTR filename;
AndroidPlaylist *playlist;
};
+64
View File
@@ -0,0 +1,64 @@
#include "../../Library/ml_pmp/pmp.h"
#include "api.h"
#include <api/service/waservicefactory.h>
api_language *WASABI_API_LNG = 0;
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
// Metadata service
api_metadata *AGAVE_API_METADATA=0;
api_playlistmanager *WASABI_API_PLAYLISTMNGR=0;
api_threadpool *WASABI_API_THREADPOOL=0;
api_albumart *AGAVE_API_ALBUMART=0;
api_memmgr *WASABI_API_MEMMGR=0;
api_application *WASABI_API_APP=0;
api_devicemanager *AGAVE_API_DEVICEMANAGER = 0;
extern PMPDevicePlugin plugin;
template <class api_T>
void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
{
if (plugin.service)
{
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
if (factory)
api_t = reinterpret_cast<api_T *>( factory->getInterface() );
}
}
template <class api_T>
void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
{
if (plugin.service && api_t)
{
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
if (factory)
factory->releaseInterface(api_t);
}
api_t = NULL;
}
void WasabiInit()
{
ServiceBuild(WASABI_API_LNG, languageApiGUID);
ServiceBuild(AGAVE_API_METADATA, api_metadataGUID);
ServiceBuild(WASABI_API_PLAYLISTMNGR, api_playlistmanagerGUID);
ServiceBuild(WASABI_API_THREADPOOL, ThreadPoolGUID);
ServiceBuild(AGAVE_API_ALBUMART, albumArtGUID);
ServiceBuild(WASABI_API_MEMMGR, memMgrApiServiceGuid);
ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
ServiceBuild(AGAVE_API_DEVICEMANAGER, DeviceManagerGUID);
}
void WasabiQuit()
{
ServiceRelease(WASABI_API_LNG, languageApiGUID);
ServiceRelease(WASABI_API_PLAYLISTMNGR, api_playlistmanagerGUID);
ServiceRelease(AGAVE_API_METADATA, api_metadataGUID);
ServiceRelease(WASABI_API_THREADPOOL, ThreadPoolGUID);
ServiceRelease(AGAVE_API_ALBUMART, albumArtGUID);
ServiceRelease(WASABI_API_MEMMGR, memMgrApiServiceGuid);
ServiceRelease(WASABI_API_APP, applicationApiServiceGuid);
ServiceRelease(AGAVE_API_DEVICEMANAGER, DeviceManagerGUID);
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include "../Agave/Language/api_language.h"
#include "../Agave/Metadata/api_metadata.h"
extern api_metadata *metadataApi;
#define AGAVE_API_METADATA metadataApi
#include "../playlist/api_playlistmanager.h"
extern api_playlistmanager *playlistManagerApi;
#define WASABI_API_PLAYLISTMNGR playlistManagerApi
#include "../nu/threadpool/api_threadpool.h"
extern api_threadpool *threadPoolApi;
#define WASABI_API_THREADPOOL threadPoolApi
#include "../Agave/AlbumArt/api_albumart.h"
extern api_albumart *albumArtApi;
#define AGAVE_API_ALBUMART albumArtApi
#include <api/memmgr/api_memmgr.h>
extern api_memmgr *memmgr;
#define WASABI_API_MEMMGR memmgr
#include <api/application/api_application.h>
extern api_application *applicationApi;
#define WASABI_API_APP applicationApi
#include "../devices/api_devicemanager.h"
extern api_devicemanager *deviceManagerApi;
#define AGAVE_API_DEVICEMANAGER deviceManagerApi
void WasabiInit();
void WasabiQuit();
@@ -0,0 +1,343 @@
#include "api.h"
#include "./deviceprovider.h"
#include "../devices/api_devicemanager.h"
extern PMPDevicePlugin plugin;
void connectDrive(wchar_t drive, bool checkSize, bool checkBlacklist);
static size_t tlsIndex = (size_t)-1;
static BOOL
DiscoveryProvider_RegisterCancelSwitch(BOOL *cancelSwitch)
{
if ((size_t)-1 != tlsIndex &&
NULL != WASABI_API_APP)
{
WASABI_API_APP->SetThreadStorage(tlsIndex, cancelSwitch);
return TRUE;
}
return FALSE;
}
static BOOL
DiscoveryProvider_GetCancelSwitchOn()
{
if ((size_t)-1 != tlsIndex &&
NULL != WASABI_API_APP)
{
BOOL *cancelSwitch = (BOOL*)WASABI_API_APP->GetThreadStorage(tlsIndex);
if (NULL != cancelSwitch &&
FALSE != *cancelSwitch)
{
return TRUE;
}
}
return FALSE;
}
static void
DeviceProvider_DriverEnumCb(wchar_t drive, unsigned int type)
{
if (DRIVE_REMOVABLE == type &&
FALSE == DiscoveryProvider_GetCancelSwitchOn())
{
connectDrive(drive,true,true);
}
}
DeviceProvider::DeviceProvider()
: ref(1), activity(0), manager(NULL), readyEvent(NULL), cancelDiscovery(FALSE)
{
InitializeCriticalSection(&lock);
enumerator = (ENUMDRIVES)SendMessageW(plugin.hwndPortablesParent,
WM_PMP_IPC, 0, PMP_IPC_ENUM_ACTIVE_DRIVES);
}
DeviceProvider::~DeviceProvider()
{
CancelDiscovery();
if (NULL != readyEvent)
CloseHandle(readyEvent);
DeleteCriticalSection(&lock);
}
HRESULT DeviceProvider::CreateInstance(DeviceProvider **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new DeviceProvider();
if (NULL == *instance)
return E_OUTOFMEMORY;
return S_OK;
}
size_t DeviceProvider::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t DeviceProvider::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int DeviceProvider::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object)
return E_POINTER;
if (IsEqualIID(interface_guid, IFC_DeviceProvider))
*object = static_cast<ifc_deviceprovider*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void DeviceProvider::Lock()
{
EnterCriticalSection(&lock);
}
void DeviceProvider::Unlock()
{
LeaveCriticalSection(&lock);
}
DWORD DeviceProvider::DiscoveryThread()
{
IncrementActivity();
if (NULL != enumerator &&
FALSE == cancelDiscovery)
{
DiscoveryProvider_RegisterCancelSwitch(&cancelDiscovery);
enumerator(DeviceProvider_DriverEnumCb);
DiscoveryProvider_RegisterCancelSwitch(NULL);
}
DecrementActivity();
Lock();
if (NULL != readyEvent)
SetEvent(readyEvent);
Unlock();
return 0;
}
static int DeviceProvider_DiscoveryThreadStarter(HANDLE handle, void *user, intptr_t id)
{
DeviceProvider *self;
DWORD result;
self = (DeviceProvider*)user;
if (NULL != self)
result = self->DiscoveryThread();
else
result = -2;
return result;
}
HRESULT DeviceProvider::BeginDiscovery(api_devicemanager *manager)
{
HRESULT hr;
if (NULL == enumerator)
return E_UNEXPECTED;
Lock();
if (NULL != readyEvent &&
WAIT_TIMEOUT == WaitForSingleObject(readyEvent, 0))
{
hr = E_PENDING;
}
else
{
hr = S_OK;
if (NULL == readyEvent)
{
readyEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (NULL == readyEvent)
hr = E_FAIL;
}
if ((size_t)-1 == tlsIndex &&
NULL != WASABI_API_APP)
{
tlsIndex = WASABI_API_APP->AllocateThreadStorage();
}
if (SUCCEEDED(hr))
{
cancelDiscovery = FALSE;
ResetEvent(readyEvent);
if (0 != WASABI_API_THREADPOOL->RunFunction(0, DeviceProvider_DiscoveryThreadStarter,
this, 0, api_threadpool::FLAG_LONG_EXECUTION))
{
SetEvent(readyEvent);
hr = E_FAIL;
}
}
}
Unlock();
return hr;
}
HRESULT DeviceProvider::CancelDiscovery()
{
HRESULT hr;
hr = S_FALSE;
Lock();
if (NULL != readyEvent)
{
cancelDiscovery = TRUE;
if (WAIT_OBJECT_0 == WaitForSingleObject(readyEvent, 0))
hr = S_OK;
cancelDiscovery = FALSE;
}
Unlock();
return hr;
}
HRESULT DeviceProvider::GetActive()
{
HRESULT hr;
Lock();
if (0 != activity)
hr = S_OK;
else
hr = S_FALSE;
Unlock();
return hr;
}
HRESULT DeviceProvider::Register(api_devicemanager *manager)
{
HRESULT hr;
if (NULL != this->manager)
return E_UNEXPECTED;
if (NULL == manager)
return E_POINTER;
hr = manager->RegisterProvider(this);
if (SUCCEEDED(hr))
{
this->manager = manager;
manager->AddRef();
}
return hr;
}
HRESULT DeviceProvider::Unregister()
{
HRESULT hr;
if (NULL == manager)
return E_UNEXPECTED;
hr = manager->UnregisterProvider(this);
manager->Release();
manager = NULL;
return hr;
}
size_t DeviceProvider::IncrementActivity()
{
size_t a;
Lock();
activity++;
if (1 == activity &&
NULL != manager)
{
manager->SetProviderActive(this, TRUE);
}
a = activity;
Unlock();
return a;
}
size_t DeviceProvider::DecrementActivity()
{
size_t a;
Lock();
if (0 != activity)
{
activity--;
if (0 == activity &&
NULL != manager)
{
manager->SetProviderActive(this, FALSE);
}
}
a = activity;
Unlock();
return a;
}
#define CBCLASS DeviceProvider
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
CB(API_BEGINDISCOVERY, BeginDiscovery)
CB(API_CANCELDISCOVERY, CancelDiscovery)
CB(API_GETACTIVE, GetActive)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,50 @@
#pragma once
#include <wtypes.h>
#include "../devices/ifc_deviceprovider.h"
#include "../../Library/ml_pmp/pmp.h"
class DeviceProvider : public ifc_deviceprovider
{
protected:
DeviceProvider();
~DeviceProvider();
public:
static HRESULT CreateInstance(DeviceProvider **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_deviceprovider */
HRESULT BeginDiscovery(api_devicemanager *manager);
HRESULT CancelDiscovery();
HRESULT GetActive();
public:
HRESULT Register(api_devicemanager *manager);
HRESULT Unregister();
size_t IncrementActivity();
size_t DecrementActivity();
private:
void Lock();
void Unlock();
DWORD DiscoveryThread();
friend static int DeviceProvider_DiscoveryThreadStarter(HANDLE handle, void *user_data, intptr_t id);
protected:
size_t ref;
size_t activity;
CRITICAL_SECTION lock;
api_devicemanager *manager;
ENUMDRIVES enumerator;
HANDLE readyEvent;
BOOL cancelDiscovery;
protected:
RECVS_DISPATCH;
};
+138
View File
@@ -0,0 +1,138 @@
// this file almost totally copied from MSDN
#include <windows.h>
#include <stdio.h>
#include <winioctl.h>
#define LOCK_TIMEOUT 3000 // 10 Seconds
#define LOCK_RETRIES 20
static HANDLE OpenVolume(TCHAR cDriveLetter)
{
HANDLE hVolume;
UINT uDriveType;
wchar_t szVolumeName[8] = {0};
wchar_t szRootName[5] = {0};
DWORD dwAccessFlags = 0;
wsprintf(szRootName, L"%c:\\", cDriveLetter);
uDriveType = GetDriveType(szRootName);
switch(uDriveType) {
case DRIVE_REMOVABLE:
dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
break;
case DRIVE_CDROM:
dwAccessFlags = GENERIC_READ;
break;
default:
printf("Cannot eject. Drive type is incorrect.\n");
return INVALID_HANDLE_VALUE;
}
wsprintf(szVolumeName, L"\\\\.\\%c:", cDriveLetter);
hVolume = CreateFile( szVolumeName,
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if (hVolume == INVALID_HANDLE_VALUE)
printf("CreateFile error %d\n", GetLastError());
return hVolume;
}
static BOOL CloseVolume(HANDLE hVolume)
{
return CloseHandle(hVolume);
}
static BOOL LockVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
DWORD dwSleepAmount;
int nTryCount;
dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;
// Do this in a loop until a timeout period has expired
for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
if (DeviceIoControl(hVolume,
FSCTL_LOCK_VOLUME,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL))
return TRUE;
Sleep(dwSleepAmount);
}
return FALSE;
}
static BOOL DismountVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
return DeviceIoControl( hVolume,
FSCTL_DISMOUNT_VOLUME,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL);
}
static BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
{
DWORD dwBytesReturned;
PREVENT_MEDIA_REMOVAL PMRBuffer;
PMRBuffer.PreventMediaRemoval = fPreventRemoval;
return DeviceIoControl( hVolume,
IOCTL_STORAGE_MEDIA_REMOVAL,
&PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
NULL, 0,
&dwBytesReturned,
NULL);
}
static int AutoEjectVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
return DeviceIoControl( hVolume,
IOCTL_STORAGE_EJECT_MEDIA,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL);
}
BOOL EjectVolume(TCHAR cDriveLetter)
{
HANDLE hVolume;
BOOL fAutoEject = FALSE;
hVolume = OpenVolume(cDriveLetter);
if (hVolume == INVALID_HANDLE_VALUE)
return FALSE;
// Lock and dismount the volume.
if (LockVolume(hVolume) && DismountVolume(hVolume)) {
// Set prevent removal to false and eject the volume.
if (PreventRemovalOfVolume(hVolume, FALSE) && AutoEjectVolume(hVolume))
fAutoEject = TRUE;
}
// Close the volume so other processes can use the drive.
if (!CloseVolume(hVolume))
return FALSE;
if (fAutoEject) return TRUE;
else return FALSE;
}
@@ -0,0 +1,67 @@
#include "api.h"
#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include "resource.h"
#include <strsafe.h>
typedef struct CopyData
{
void * callbackContext;
void (*callback)(void * callbackContext, wchar_t * status);
} CopyData;
DWORD CALLBACK CopyToIpodProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred,
LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred,
DWORD dwStreamNumber,
DWORD dwCallbackReason,
HANDLE hSourceFile, HANDLE hDestinationFile,
LPVOID lpData)
{
CopyData *inst = (CopyData *)lpData;
if (inst && inst->callback)
{
wchar_t status[100] = {0};
wchar_t langtemp[100] = {0};
StringCbPrintf(status, sizeof(status), WASABI_API_LNGSTRINGW_BUF(IDS_TRANSFERING_PERCENT, langtemp, 100), (int)(100ULL * TotalBytesTransferred.QuadPart / (TotalFileSize.QuadPart)));
inst->callback(inst->callbackContext,status);
}
return PROGRESS_CONTINUE;
}
int CopyFile(const wchar_t *infile, const wchar_t *outfile, void * callbackContext, void (*callback)(void * callbackContext, wchar_t * status), int * killswitch)
{
wchar_t langtemp[100] = {0};
CopyData c;
c.callback = callback;
c.callbackContext = callbackContext;
if (CopyFileEx(infile, outfile, CopyToIpodProgressRoutine, &c, killswitch,0))
{
if (callback)
{
callback(callbackContext, WASABI_API_LNGSTRINGW_BUF(IDS_DONE, langtemp, 100));
}
return 0;
}
else
{
switch(GetLastError())
{
case ERROR_REQUEST_ABORTED:
DeleteFile(outfile);
if (callback)
{
callback(callbackContext, WASABI_API_LNGSTRINGW_BUF(IDS_CANCELLED, langtemp, 100));
}
default:
if (callback)
{
callback(callbackContext, WASABI_API_LNGSTRINGW_BUF(IDS_TRANSFER_FAILED, langtemp, 100));
}
}
return -1;
}
}
+601
View File
@@ -0,0 +1,601 @@
#include "../../Library/ml_pmp/pmp.h"
#include "../Winamp/wa_ipc.h"
#include <vector>
#include "../nu/AutoWide.h"
#include "../nu/AutoChar.h"
#include "../nu/Alias.h"
#include <api/service/waServiceFactory.h>
#include "api.h"
#include "resource.h"
#include "androiddevice.h"
#include "deviceprovider.h"
#include <devguid.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <strsafe.h>
#define PLUGIN_VERSION L"1.72"
static int Init();
static void Quit();
static bool doRegisterForDevNotification(void);
static intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3);
extern PMPDevicePlugin plugin = {PMPHDR_VER,0,Init,Quit,MessageProc};
// start-android
static const wchar_t *winampini;
static std::vector<wchar_t*> blacklist;
bool loading_devices[26] = {0,};
static HDEVNOTIFY hDevNotify;
std::vector<AndroidDevice*> devices;
HWND config;
static DeviceProvider *deviceProvider = NULL;
static UINT_PTR rescanTimer = 0;
static void blacklistLoad() {
wchar_t keyname[64] = {0};
int l = GetPrivateProfileIntW(L"pmp_android", L"blacklistnum", 0, winampini);
for(int i=l>100?l-100:0; i<l; i++) {
wchar_t buf[100] = {0};
StringCchPrintfW(keyname, 64, L"blacklist-%d", i);
GetPrivateProfileStringW(L"pmp_android", keyname, L"", buf, 100, winampini);
if(buf[0])
{
blacklist.push_back(_wcsdup(buf));
}
}
}
static void blacklistSave() {
wchar_t buf[64] = {0};
StringCchPrintfW(buf, 64, L"%d", blacklist.size());
WritePrivateProfileStringW(L"pmp_android", L"blacklistnum", buf, winampini);
for(size_t i=0; i<blacklist.size(); i++)
{
StringCchPrintfW(buf, 64, L"blacklist-%d", i);
WritePrivateProfileStringW(L"pmp_android", buf, (const wchar_t*)blacklist.at(i), winampini);
}
}
static wchar_t *makeBlacklistString(wchar_t drive) {
wchar_t path[4]={drive,L":\\"};
wchar_t name[100]=L"";
wchar_t buf[FIELD_LENGTH]=L"";
DWORD serial=0;
UINT olderrmode=SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
GetVolumeInformation(path,name,100,&serial,NULL,NULL,NULL,0);
if(serial)
{
StringCchPrintf(buf, FIELD_LENGTH, L"s:%d",serial);
SetErrorMode(olderrmode);
return _wcsdup(buf);
}
{
ULARGE_INTEGER tfree={0,}, total={0,}, freeb={0,};
GetDiskFreeSpaceEx(path, &tfree, &total, &freeb);
StringCchPrintf(buf, FIELD_LENGTH, L"n:%s,%d,%d", name, total.HighPart, total.LowPart);
SetErrorMode(olderrmode);
return _wcsdup(buf);
}
}
static bool blacklistCheck(wchar_t drive)
{
wchar_t *s = makeBlacklistString(drive);
if (s)
{
for(size_t i=0; i<blacklist.size(); i++)
{
if(!wcscmp(s,(wchar_t*)blacklist.at(i)))
{
free(s);
return true;
}
}
free(s);
}
return false;
}
static bool blacklistAdd(const wchar_t drive)
{
wchar_t *s = makeBlacklistString(drive);
if (s)
{
for(size_t i=0; i<blacklist.size(); i++)
{
if(!wcscmp(s,(wchar_t*)blacklist.at(i)))
{
free(s);
return false;
}
}
blacklist.push_back(s);
}
return true;
}
static BOOL
Device_IsiPod(const wchar_t drive)
{
const wchar_t test[] = {drive, L":\\iPod_Control"};
WIN32_FIND_DATAW findData;
HANDLE file = FindFirstFileW(test, &findData);
if (INVALID_HANDLE_VALUE != file)
{
FindClose(file);
if (0 != (FILE_ATTRIBUTE_DIRECTORY & findData.dwFileAttributes))
return TRUE;
}
return FALSE;
}
static BOOL
Device_IsAndroid(const wchar_t drive)
{
const wchar_t test[] = {drive, L":\\Android"};
WIN32_FIND_DATAW findData;
HANDLE file = FindFirstFileW(test, &findData);
if (INVALID_HANDLE_VALUE != file)
{
FindClose(file);
if (0 != (FILE_ATTRIBUTE_DIRECTORY & findData.dwFileAttributes))
return TRUE;
}
return FALSE;
}
static BOOL
Device_IsSizeOk(const wchar_t drive)
{
const wchar_t test[] = {drive, L":\\"};
ULARGE_INTEGER total;
if (0 == GetDiskFreeSpaceExW(test, NULL, &total, NULL) ||
total.HighPart == 0 && total.LowPart == 0)
{
return FALSE;
}
return TRUE;
}
static BOOL
Device_IsOkToConnect(const wchar_t drive)
{
const wchar_t test[] = {drive, TEXT(":\\Winamp\\")TAG_CACHE};
wchar_t title[128] = {0};
wchar_t message[1024] = {0};
int result;
if (FALSE != PathFileExistsW(test))
return TRUE;
StringCbPrintfW(message, sizeof(message), WASABI_API_LNGSTRINGW(IDS_REMOVEABLE_DRIVE_DETECTED),
towupper(drive));
WASABI_API_LNGSTRINGW_BUF(IDS_WINAMP_PMP_SUPPORT,title,ARRAYSIZE(title));
result = MessageBoxW(NULL, message, title,
MB_YESNO | MB_SETFOREGROUND | MB_TOPMOST |
MB_ICONINFORMATION);
if(IDNO == result)
{
return FALSE;
}
return TRUE;
}
static Nullsoft::Utility::LockGuard connect_guard;
static int ThreadFunc_Load(HANDLE handle, void *user_data, intptr_t id)
{
wchar_t drive = (wchar_t)id;
if (FALSE == Device_IsOkToConnect(drive))
{
Nullsoft::Utility::AutoLock connect_lock(connect_guard);
blacklistAdd(drive);
blacklistSave();
}
else
{
pmpDeviceLoading load;
Device * d = new AndroidDevice(drive,&load);
}
loading_devices[drive-'A'] = false;
deviceProvider->DecrementActivity();
return 0;
}
//#include <WinIoCtl.h>
void connectDrive(wchar_t drive, bool checkSize=true, bool checkBlacklist=true)
{
Nullsoft::Utility::AutoLock connect_lock(connect_guard);
// capitalize
if (drive >= 'a' && drive <= 'z')
drive = drive - 32;
// reject invalid drive letters
if (drive < 'A' || drive > 'Z')
return;
if(checkBlacklist && blacklistCheck(drive))
return;
// if device is taken already ignore
for (std::vector<AndroidDevice*>::const_iterator e = devices.begin(); e != devices.end(); e++)
{
if ((*e)->drive == drive)
return;
}
if (loading_devices[drive-'A'])
return;
loading_devices[drive-'A'] = true;
if(FALSE == checkSize || FALSE != Device_IsSizeOk(drive))
{
if (FALSE != Device_IsAndroid(drive) &&
FALSE == Device_IsiPod(drive))
{
deviceProvider->IncrementActivity();
if (NULL != WASABI_API_THREADPOOL &&
0 == WASABI_API_THREADPOOL->RunFunction(0, ThreadFunc_Load, 0,
(int)drive, api_threadpool::FLAG_LONG_EXECUTION))
{
return;
}
deviceProvider->DecrementActivity();
}
}
loading_devices[drive-'A'] = false;
}
static void autoDetectCallback(wchar_t drive,UINT type)
{
if(type == DRIVE_REMOVABLE)
{
connectDrive(drive, true, true);
}
}
// end-android
static int Init()
{
WasabiInit();
// start-android
winampini = (const wchar_t*)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_GETINIFILEW);
// need to have this initialised before we try to do anything with localisation features
WASABI_API_START_LANG(plugin.hDllInstance,PmpAndroidLangGUID);
// end-android
static wchar_t szDescription[256];
StringCchPrintfW(szDescription, ARRAYSIZE(szDescription),
WASABI_API_LNGSTRINGW(IDS_NULLSOFT_ANDROID_DEVICE_PLUGIN), PLUGIN_VERSION);
plugin.description = szDescription;
/** load up the backlist */
blacklistLoad();
if (NULL != AGAVE_API_DEVICEMANAGER &&
NULL == deviceProvider)
{
if (SUCCEEDED(DeviceProvider::CreateInstance(&deviceProvider)) &&
FAILED(deviceProvider->Register(AGAVE_API_DEVICEMANAGER)))
{
deviceProvider->Release();
deviceProvider = NULL;
}
}
/* Our device shows up as a normal drive */
if (NULL == deviceProvider ||
FAILED(deviceProvider->BeginDiscovery(AGAVE_API_DEVICEMANAGER)))
{
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)autoDetectCallback,PMP_IPC_ENUM_ACTIVE_DRIVES);
}
return 0;
}
static void Quit()
{
if (NULL != deviceProvider)
{
deviceProvider->Unregister();
deviceProvider->Release();
deviceProvider = NULL;
}
WasabiQuit();
UnregisterDeviceNotification(hDevNotify);
AndroidDevice::CloseDatabase();
}
static wchar_t FirstDriveFromMask(ULONG *unitmask) {
char i;
ULONG adj = 0x1, mask = *unitmask;
for(i=0; i<26; ++i) {
if(mask & 0x1) {
*unitmask -= adj;
break;
}
adj = adj << 1;
mask = mask >> 1;
}
return (i+L'A');
}
static int GetNumberOfDrivesFromMask(ULONG unitmask) {
int count = 0;
for(int i=0; i<26; ++i)
{
if(unitmask & 0x1)
count++;
unitmask = unitmask >> 1;
}
return count;
}
static void CALLBACK RescanOnTimer(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
KillTimer(hwnd, idEvent);
if (idEvent == rescanTimer)
rescanTimer = 0;
if (NULL == deviceProvider ||
FAILED(deviceProvider->BeginDiscovery(AGAVE_API_DEVICEMANAGER)))
{
PostMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)autoDetectCallback,PMP_IPC_ENUM_ACTIVE_DRIVES);
}
}
int wmDeviceChange(WPARAM wParam, LPARAM lParam)
{
UINT olderrmode=SetErrorMode(SEM_FAILCRITICALERRORS);
if(wParam==DBT_DEVICEARRIVAL || wParam==DBT_DEVICEREMOVECOMPLETE)
{ // something has been inserted or removed
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
if(lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)
{ // its a volume
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
if((!(lpdbv->dbcv_flags & DBTF_MEDIA) && !(lpdbv->dbcv_flags & DBTF_NET)))
{ // its not a network drive or a CD/floppy, game on!
ULONG dbcv_unitmask = lpdbv->dbcv_unitmask;
// see just how many drives have been flagged on the action
// eg one android drive could have multiple partitions that we handle
int count = GetNumberOfDrivesFromMask(dbcv_unitmask);
for(int j = 0; j < count; j++)
{
wchar_t drive = FirstDriveFromMask(&dbcv_unitmask);
if((wParam == DBT_DEVICEARRIVAL) && !blacklistCheck(drive))
{ // connected
connectDrive(drive);
//send a message as if the user just selected a drive from the combo box, this way the fields are refreshed to the correct device's settings
SendMessage(config, WM_COMMAND,MAKEWPARAM(IDC_DRIVESELECT,CBN_SELCHANGE),0);
}
else
{ // removal
for(size_t i=0; i < devices.size(); i++)
{
AndroidDevice * d = (AndroidDevice*)devices.at(i);
if(d->drive == drive)
{
devices.erase(devices.begin() + i);
if(config) SendMessage(config,WM_USER,0,0); //refresh fields
if(config) SendMessage(config,WM_COMMAND, MAKEWPARAM(IDC_DRIVESELECT,CBN_SELCHANGE),0); //update to correct device change as if the user had clicked on the combo box themself
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)d,PMP_IPC_DEVICEDISCONNECTED);
delete d;
i--;
}
}
}
}
}
}
}
else
{
rescanTimer = SetTimer(NULL, rescanTimer, 10000, RescanOnTimer);
}
SetErrorMode(olderrmode);
return 0;
}
static int IsDriveConnectedToPMP(wchar_t drive)
{
for(size_t i = 0; i < devices.size(); i++)
{
if(((AndroidDevice*)devices.at(i))->drive == drive)
{
return 1;
}
}
return 0;
}
static INT_PTR CALLBACK config_dialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
{
for(wchar_t d=L'A'; d<='Z'; d++)
{
wchar_t drive[3] = {d,L':',0}, drv[4] = {d,L':','\\',0};
UINT uDriveType = GetDriveType(drv);
if(uDriveType == DRIVE_REMOVABLE || uDriveType == DRIVE_CDROM || uDriveType == DRIVE_FIXED) {
int position = (int)SendDlgItemMessageW(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_ADDSTRING,0,(LPARAM)drive);
SendDlgItemMessage(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_SETITEMDATA,position,d);
}
}
SendDlgItemMessage(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_SETCURSEL,0,0);
SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_COMBO_MANUALCONNECT,CBN_SELCHANGE),0);
}
break;
case WM_CLOSE:
EndDialog(hwndDlg,0);
break;
case WM_COMMAND:
switch(LOWORD(wParam)) {
case IDC_COMBO_MANUALCONNECT:
{
if(HIWORD(wParam)==CBN_SELCHANGE) {
int indx = (int)SendDlgItemMessageW(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_GETCURSEL,0,0);
wchar_t drive = (wchar_t)SendDlgItemMessage(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_GETITEMDATA,indx,0);
if(indx >= 0)
{
int connected = IsDriveConnectedToPMP(drive), isblacklisted = blacklistCheck(drive);
EnableWindow(GetDlgItem(hwndDlg, IDC_MANUALCONNECT), !connected && !isblacklisted);
EnableWindow(GetDlgItem(hwndDlg, IDC_MANUALDISCONNECT), connected);
EnableWindow(GetDlgItem(hwndDlg, IDC_MANUALBLACKLIST), TRUE);
SetDlgItemText(hwndDlg, IDC_MANUALBLACKLIST, WASABI_API_LNGSTRINGW(isblacklisted ? IDS_UNBLACKLIST_DRIVE : IDS_BLACKLIST_DRIVE));
}
}
}
break;
case IDC_MANUALCONNECT:
{
char titleStr[32] = {0};
if(MessageBoxA(hwndDlg, WASABI_API_LNGSTRING(IDS_MANUAL_CONNECT_PROMPT),
WASABI_API_LNGSTRING_BUF(IDS_WARNING,titleStr,32), MB_YESNO) == IDYES)
{
int indx = (int)SendDlgItemMessageW(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_GETCURSEL,0,0);
wchar_t drive = (wchar_t)SendDlgItemMessage(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_GETITEMDATA,indx,0);
if(drive >= L'A' && drive <= L'Z') {
wchar_t *bl = makeBlacklistString(drive);
if (bl)
{
for(size_t i=0; i<blacklist.size(); i++)
{
if(!wcscmp(bl,(wchar_t*)blacklist.at(i)))
{
free(blacklist.at(i));
blacklist.erase(blacklist.begin() + i);
break;
}
}
free(bl);
}
connectDrive(drive,false);
// should do a better check here incase of failure, etc
EnableWindow(GetDlgItem(hwndDlg, IDC_MANUALCONNECT), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_MANUALDISCONNECT), TRUE);
}
}
}
break;
case IDC_MANUALDISCONNECT:
{
int indx = (int)SendDlgItemMessageW(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_GETCURSEL,0,0);
wchar_t drive = (wchar_t)SendDlgItemMessage(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_GETITEMDATA,indx,0);
if(drive >= L'A' && drive <= L'Z')
{
for(size_t i=0; i < devices.size(); i++)
{
AndroidDevice * d = (AndroidDevice*)devices.at(i);
if(d->drive == drive)
{
devices.erase(devices.begin() + i);
if(config) SendMessage(config,WM_USER,0,0); //refresh fields
if(config) SendMessage(config,WM_COMMAND, MAKEWPARAM(IDC_DRIVESELECT,CBN_SELCHANGE),0); //update to correct device change as if the user had clicked on the combo box themself
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)d,PMP_IPC_DEVICEDISCONNECTED);
SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_COMBO_MANUALCONNECT,CBN_SELCHANGE),0);
delete d;
i--;
}
}
}
}
break;
case IDC_MANUALBLACKLIST:
{
int indx = (int)SendDlgItemMessageW(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_GETCURSEL,0,0);
wchar_t drive = (wchar_t)SendDlgItemMessage(hwndDlg,IDC_COMBO_MANUALCONNECT,CB_GETITEMDATA,indx,0);
if(drive >= L'A' && drive <= L'Z') {
wchar_t *bl = makeBlacklistString(drive);
if (bl)
{
if(!blacklistCheck(drive)) {
blacklist.push_back(bl);
// see if we've got a connected drive and prompt to remove it or wait till restart
if(IsDriveConnectedToPMP(drive)) {
wchar_t title[96] = {0};
GetWindowText(hwndDlg, title, 96);
if(MessageBox(hwndDlg,WASABI_API_LNGSTRINGW(IDS_DRIVE_CONNECTED_DISCONNECT_Q),title,MB_YESNO)==IDYES){
SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_MANUALDISCONNECT,0),0);
}
}
}
else
{
for(size_t i=0; i < blacklist.size(); i++)
{
if(!wcscmp(bl,(wchar_t*)blacklist.at(i)))
{
free(blacklist.at(i));
blacklist.erase(blacklist.begin() + i);
break;
}
}
free(bl);
}
}
SendMessage(hwndDlg,WM_COMMAND,MAKEWPARAM(IDC_COMBO_MANUALCONNECT,CBN_SELCHANGE),0);
}
}
break;
case IDOK:
case IDCANCEL:
blacklistSave();
EndDialog(hwndDlg,0);
break;
}
break;
}
return 0;
}
static intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3)
{
switch(msg) {
case PMP_DEVICECHANGE:
return wmDeviceChange(param1,param2);
case PMP_CONFIG:
WASABI_API_DIALOGBOXW(IDD_CONFIG_GLOBAL,(HWND)param1,config_dialogProc);
return 1;
}
return 0;
}
extern "C" __declspec(dllexport) PMPDevicePlugin *winampGetPMPDevicePlugin()
{
return &plugin;
}
@@ -0,0 +1,209 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// PNG
//
IDB_ANDROID_160 PNG "resources\\generic_android.png"
IDR_ANDROID_ICON PNG "resources\\androidIcon.png"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_CONFIG DIALOGEX 0, 0, 264, 226
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
EXSTYLE WS_EX_CONTROLPARENT
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "File Name Format",IDC_STATIC,7,10,56,8
EDITTEXT IDC_NAMEFORMAT,80,7,127,14,ES_AUTOHSCROLL
PUSHBUTTON "Format Help",IDC_FILENAMEHELP,211,7,46,14
LTEXT "Playlist Directory",IDC_STATIC,7,26,54,8
EDITTEXT IDC_PLDIR,80,24,128,14,ES_AUTOHSCROLL
PUSHBUTTON "Browse...",IDC_PLBROWSE,211,23,46,14
LTEXT "Supported Formats",IDC_STATIC,7,42,62,8
EDITTEXT IDC_SUPPORTEDFORMATS,80,40,128,14,ES_AUTOHSCROLL
PUSHBUTTON "Syntax Help",IDC_FORMATSHELP,211,40,46,14
LTEXT "Delete Empty Folders",IDC_STATIC,7,55,69,8
CONTROL "",IDC_PURGEFOLDERS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,80,56,8,8
PUSHBUTTON "Save and Rescan",IDC_RESCAN,7,71,66,14
PUSHBUTTON "Refresh Cache",IDC_REFRESHCACHE,79,71,66,14
GROUPBOX "Playlist Writing Options",IDC_STATIC,7,95,250,49
COMBOBOX IDC_PL_WRITE_COMBO,12,108,120,35,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LTEXT "Changing how Winamp saves its playlists may improve compatability with other portable devices.",IDC_STATIC,137,104,113,34
LTEXT "",IDC_PL_WRITE_EG,12,126,120,10
END
IDD_CONFIG_GLOBAL DIALOGEX 0, 0, 196, 90
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Android Device Support Configuration"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Select the Drive to use from the available list below",IDC_STATIC,5,3,186,67
COMBOBOX IDC_COMBO_MANUALCONNECT,31,17,40,242,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Connect Drive",IDC_MANUALCONNECT,75,17,90,13
PUSHBUTTON "Disconnect Drive",IDC_MANUALDISCONNECT,75,34,90,13
PUSHBUTTON "Blacklist Drive",IDC_MANUALBLACKLIST,75,51,90,13
DEFPUSHBUTTON "Close",IDOK,75,73,45,13
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_CONFIG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 257
TOPMARGIN, 7
BOTTOMMARGIN, 218
END
IDD_CONFIG_GLOBAL, DIALOG
BEGIN
LEFTMARGIN, 5
RIGHTMARGIN, 191
TOPMARGIN, 3
BOTTOMMARGIN, 86
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_NULLSOFT_ANDROID_DEVICE_PLUGIN "Nullsoft Android Device Plug-in v%s"
65535 "{EBFF6E00-39D8-45e6-B3EC-E3B07A45E6B0}"
END
STRINGTABLE
BEGIN
IDS_CANNOT_OPEN_FILE "Cannot open file"
IDS_CANNOT_CREATE_FILE "Cannot create file"
IDS_TRANSFERING_PERCENT "Transferring %d%%"
IDS_CANCELLED "Cancelled"
IDS_DONE "Done"
IDS_TRANSFER_FAILED "Transfer failed"
IDS_REMOVEABLE_DRIVE_DETECTED
"Winamp has detected an Android device on %c:.\nIs this a device that you want to manage with Winamp?"
IDS_WINAMP_PMP_SUPPORT "Winamp Portable Music Player Support"
IDS_MANUAL_CONNECT_PROMPT
"Manually connecting the wrong device could cause problems.\nPlease be sure that you have entered a valid Android device letter.\n\nAre you sure you wish to continue?"
IDS_WARNING "Warning"
IDS_LOADING_DRIVE_X "Loading Drive X:"
IDS_FAILED_TO_EJECT_DRIVE
"Failed to eject device. Is something else using it?"
IDS_ERROR "Error"
IDS_ANDROID_DRIVE_X "ANDROID Drive X:"
IDS_TRACK_IN_USE "Track is in use - Could not delete!"
END
STRINGTABLE
BEGIN
IDS_CACHE_UPDATED "Cache updated."
IDS_SUCCESS "Success"
IDS_FILENAME_FORMATTING_INFO
"You may enter a filename format string for your files.\nIt can contain \\ or / to delimit a path, and the following keywords:\n\n <Artist> - inserts the artist with the default capitalization\n <ARTIST> - inserts the artist in all uppercase\n <artist> - inserts the artist in all lowercase\n <Albumartist>/<ALBUMARTIST>/<albumartist> - inserts the album artist\n <Album>/<ALBUM>/<album> - inserts the album\n <year> - inserts the album year\n <Genre>/<GENRE>/<genre> - inserts the album genre\n <Title>/<TITLE>/<title> - inserts the track title\n <filename> - inserts the original filename (extension safe)\n <disc> - inserts the disc number\n #, ##, or ### - inserts the track number, with leading 0s if ## or ###\n\n For Example: E:\\Music\\<Artist>\\<Album>\\## - <Title>\n"
IDS_FILENAME_FORMAT_HELP "Filename Format Help"
IDS_SELECT_FOLDER_TO_LOAD_PLAYLISTS
"Please select a folder to load playlists from the device."
IDS_ERR_SELECTED_PATH_NOT_ON_DEVICE
"Error: selected path is not on device!"
IDS_SUPPORTED_FORMAT_INFO
"You may enter supported extensions in the form of\nextensions separated by semicolons.\n\nFor Example: mp3;wav;wma"
IDS_SUPPORTED_FORMAT_HELP "Supported Formats Help"
IDS_RESCAN_COMPLETE_SAVED "Rescan complete, device settings saved."
IDS_RESCAN_COMPLETE "Rescan complete"
IDS_ADVANCED "Advanced"
IDS_UNBLACKLIST_DRIVE "Un-blacklist Drive"
IDS_BLACKLIST_DRIVE "Blacklist Drive"
IDS_DRIVE_CONNECTED_DISCONNECT_Q
"The Drive you have selected to blacklist is currently connected and being managed.\n\nWould you like to disconnect the Drive now or you can wait until you restart Winamp."
IDS_SLASH_AT_START "Slash at start of paths (default)"
IDS_DOT_AT_START "Dot at start of paths"
END
STRINGTABLE
BEGIN
IDS_NO_SLASH_OR_DOT "No slash or dot at start"
IDS_EG_SLASH "e.g. \\path\\to\\file.mp3"
IDS_EG_DOT "e.g. .\\path\\to\\file.mp3"
IDS_EG_NEITHER "e.g. path\\to\\file.mp3"
IDS_DELAYLOAD_FAILURE "Android plug-in cannot load the database to write the cache file"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
@@ -0,0 +1,130 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29509.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pmp_android", "pmp_android.vcxproj", "{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}"
ProjectSection(ProjectDependencies) = postProject
{57C90706-B25D-4ACA-9B33-95CDB2427C27} = {57C90706-B25D-4ACA-9B33-95CDB2427C27}
{DABE6307-F8DD-416D-9DAC-673E2DECB73F} = {DABE6307-F8DD-416D-9DAC-673E2DECB73F}
{4D25C321-7F8B-424E-9899-D80A364BAF1A} = {4D25C321-7F8B-424E-9899-D80A364BAF1A}
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1} = {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915} = {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}
{E105A0A2-7391-47C5-86AC-718003524C3D} = {E105A0A2-7391-47C5-86AC-718003524C3D}
{255B68B5-7EF8-45EF-A675-2D6B88147909} = {255B68B5-7EF8-45EF-A675-2D6B88147909}
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bfc", "..\Wasabi\bfc\bfc.vcxproj", "{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tataki", "..\tataki\tataki.vcxproj", "{255B68B5-7EF8-45EF-A675-2D6B88147909}"
ProjectSection(ProjectDependencies) = postProject
{DABE6307-F8DD-416D-9DAC-673E2DECB73F} = {DABE6307-F8DD-416D-9DAC-673E2DECB73F}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsutil", "..\nsutil\nsutil.vcxproj", "{DABE6307-F8DD-416D-9DAC-673E2DECB73F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nde", "..\nde\nde.vcxproj", "{4D25C321-7F8B-424E-9899-D80A364BAF1A}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nx", "..\replicant\nx\nx.vcxproj", "{57C90706-B25D-4ACA-9B33-95CDB2427C27}"
ProjectSection(ProjectDependencies) = postProject
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nu", "..\replicant\nu\nu.vcxproj", "{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnetlib", "..\replicant\jnetlib\jnetlib.vcxproj", "{E105A0A2-7391-47C5-86AC-718003524C3D}"
ProjectSection(ProjectDependencies) = postProject
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A} = {0F9730E4-45DA-4BD2-A50A-403A4BC9751A}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\replicant\zlib\zlib.vcxproj", "{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}.Debug|Win32.ActiveCfg = Debug|Win32
{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}.Debug|Win32.Build.0 = Debug|Win32
{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}.Debug|x64.ActiveCfg = Debug|x64
{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}.Debug|x64.Build.0 = Debug|x64
{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}.Release|Win32.ActiveCfg = Release|Win32
{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}.Release|Win32.Build.0 = Release|Win32
{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}.Release|x64.ActiveCfg = Release|x64
{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}.Release|x64.Build.0 = Release|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.ActiveCfg = Debug|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.Build.0 = Debug|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.ActiveCfg = Debug|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.Build.0 = Debug|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.ActiveCfg = Release|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.Build.0 = Release|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.ActiveCfg = Release|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.Build.0 = Release|x64
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|Win32.ActiveCfg = Debug|Win32
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|Win32.Build.0 = Debug|Win32
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|x64.ActiveCfg = Debug|x64
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|x64.Build.0 = Debug|x64
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|Win32.ActiveCfg = Release|Win32
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|Win32.Build.0 = Release|Win32
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|x64.ActiveCfg = Release|x64
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|x64.Build.0 = Release|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.ActiveCfg = Debug|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.Build.0 = Debug|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.ActiveCfg = Debug|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.Build.0 = Debug|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.ActiveCfg = Release|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.Build.0 = Release|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.ActiveCfg = Release|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.Build.0 = Release|x64
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Debug|Win32.ActiveCfg = Debug|Win32
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Debug|Win32.Build.0 = Debug|Win32
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Debug|x64.ActiveCfg = Debug|x64
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Debug|x64.Build.0 = Debug|x64
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Release|Win32.ActiveCfg = Release|Win32
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Release|Win32.Build.0 = Release|Win32
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Release|x64.ActiveCfg = Release|x64
{4D25C321-7F8B-424E-9899-D80A364BAF1A}.Release|x64.Build.0 = Release|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.ActiveCfg = Debug|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.Build.0 = Debug|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.ActiveCfg = Debug|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.Build.0 = Debug|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.ActiveCfg = Release|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.Build.0 = Release|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.ActiveCfg = Release|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.Build.0 = Release|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.ActiveCfg = Debug|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.Build.0 = Debug|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.ActiveCfg = Debug|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.Build.0 = Debug|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.ActiveCfg = Release|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.Build.0 = Release|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.ActiveCfg = Release|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.Build.0 = Release|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.ActiveCfg = Debug|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.Build.0 = Debug|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.ActiveCfg = Debug|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.Build.0 = Debug|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.ActiveCfg = Release|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.Build.0 = Release|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.ActiveCfg = Release|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.Build.0 = Release|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.ActiveCfg = Debug|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|Win32.Build.0 = Debug|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.ActiveCfg = Debug|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Debug|x64.Build.0 = Debug|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.ActiveCfg = Release|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|Win32.Build.0 = Release|Win32
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.ActiveCfg = Release|x64
{0F9730E4-45DA-4BD2-A50A-403A4BC9751A}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C4E799C1-027B-487B-8E1A-31F2D26A1AFE}
EndGlobalSection
EndGlobal
@@ -0,0 +1,332 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{491665B2-6437-4D30-9AEC-DE7D1CB20E1E}</ProjectGuid>
<RootNamespace>pmp_android</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;..;..\..\..\;..\..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WINDOWS;_UNICODE;UNICODE;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4244;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>wsock32.lib;shlwapi.lib;fmtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalIncludeDirectories)</AdditionalLibraryDirectories>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;..;..\..\..\;..\..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WINDOWS;_UNICODE;UNICODE;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;WIN64;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4244;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>wsock32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;..;..\..\..\;..\..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WINDOWS;_UNICODE;UNICODE;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4244;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>wsock32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>.;..\..\..\Wasabi;..;..\..\..\;..\..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WINDOWS;_UNICODE;UNICODE;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;WIN64;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4244;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>wsock32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp" />
<ClCompile Include="albumart.cpp" />
<ClCompile Include="androiddevice.cpp" />
<ClCompile Include="androidplaylist.cpp" />
<ClCompile Include="androidplaylistsaver.cpp" />
<ClCompile Include="api.cpp" />
<ClCompile Include="deviceprovider.cpp" />
<ClCompile Include="eject.cpp" />
<ClCompile Include="filecopy.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="utils.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\General\gen_ml\ml.h" />
<ClInclude Include="..\..\Library\ml_pmp\pmp.h" />
<ClInclude Include="androiddevice.h" />
<ClInclude Include="androidplaylist.h" />
<ClInclude Include="androidplaylistsaver.h" />
<ClInclude Include="api.h" />
<ClInclude Include="deviceprovider.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<Image Include="resources\androidIcon.png" />
<Image Include="resources\generic_android.png" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_android.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\nde\nde.vcxproj">
<Project>{4d25c321-7f8b-424e-9899-d80a364baf1a}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\replicant\nu\nu.vcxproj">
<Project>{f1f5cd60-0d5b-4cea-9eeb-2f87ff9aa915}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\tataki\tataki.vcxproj">
<Project>{255b68b5-7ef8-45ef-a675-2d6b88147909}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\WAT\WAT.vcxproj">
<Project>{c5714908-a71f-4644-bd95-aad8ee7914da}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="albumart.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="androiddevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="androidplaylist.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="androidplaylistsaver.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="deviceprovider.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="eject.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="filecopy.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="androiddevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="androidplaylist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="androidplaylistsaver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="api.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceprovider.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\General\gen_ml\ml.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\Library\ml_pmp\pmp.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="resources\generic_android.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="resources\androidIcon.png">
<Filter>Image Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{82d6647a-a3b9-4ade-b2cc-4a360f5ed80d}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{8731ac77-4c42-42fc-8ff8-f64922843c99}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{06318ce7-b270-4a39-833a-4ab306c760ed}</UniqueIdentifier>
</Filter>
<Filter Include="Image Files">
<UniqueIdentifier>{d2febc64-2e0e-4a50-8994-0dcaab423352}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_android.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
@@ -0,0 +1,75 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by pmp_android.rc
//
#define IDS_CANNOT_OPEN_FILE 1
#define IDS_CANNOT_CREATE_FILE 2
#define IDS_TRANSFERING_PERCENT 3
#define IDS_CANCELLED 4
#define IDS_DONE 5
#define IDS_TRANSFER_FAILED 6
#define IDS_REMOVEABLE_DRIVE_DETECTED 7
#define IDS_WINAMP_PMP_SUPPORT 8
#define IDS_MANUAL_CONNECT_PROMPT 9
#define IDS_WARNING 10
#define IDS_LOADING_DRIVE_X 11
#define IDS_FAILED_TO_EJECT_DRIVE 12
#define IDS_ERROR 13
#define IDS_STRING14 14
#define IDS_ANDROID_DRIVE_X 14
#define IDS_TRACK_IN_USE 15
#define IDS_CACHE_UPDATED 16
#define IDS_SUCCESS 17
#define IDS_FILENAME_FORMATTING_INFO 18
#define IDS_FILENAME_FORMAT_HELP 19
#define IDS_SELECT_FOLDER_TO_LOAD_PLAYLISTS 20
#define IDS_ERR_SELECTED_PATH_NOT_ON_DEVICE 21
#define IDS_SUPPORTED_FORMAT_INFO 22
#define IDS_SUPPORTED_FORMAT_HELP 23
#define IDS_RESCAN_COMPLETE_SAVED 24
#define IDS_RESCAN_COMPLETE 25
#define IDS_ADVANCED 26
#define IDS_UNBLACKLIST_DRIVE 27
#define IDS_BLACKLIST_DRIVE 28
#define IDS_DRIVE_CONNECTED_DISCONNECT_Q 29
#define IDS_SLASH_AT_START 30
#define IDS_DOT_AT_START 31
#define IDS_NO_SLASH_OR_DOT 32
#define IDS_EG_SLASH 33
#define IDS_EG_DOT 34
#define IDS_STRING35 35
#define IDS_EG_NEITHER 35
#define IDS_DELAYLOAD_FAILURE 36
#define IDD_CONFIG 102
#define IDD_CONFIG_GLOBAL 105
#define IDB_ANDROID_160 110
#define IDB_PNG1 111
#define IDR_ANDROID_ICON 111
#define IDC_PLDIR 1001
#define IDC_NAMEFORMAT 1002
#define IDC_SUPPORTEDFORMATS 1003
#define IDC_DRIVESELECT 1004
#define IDC_COMBO_MANUALCONNECT 1005
#define IDC_MANUALCONNECT 1006
#define IDC_MANUALDISCONNECT 1007
#define IDC_MANUALBLACKLIST 1008
#define IDC_REFRESHCACHE 1011
#define IDC_FILENAMEHELP 1012
#define IDC_PLBROWSE 1013
#define IDC_FORMATSHELP 1014
#define IDC_RESCAN 1015
#define IDC_PURGEFOLDERS 1016
#define IDC_PL_WRITE_COMBO 1017
#define IDC_PL_WRITE_EG 1018
#define IDS_NULLSOFT_ANDROID_DEVICE_PLUGIN 65534
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 113
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1019
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 197 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

+334
View File
@@ -0,0 +1,334 @@
#include <windows.h>
#include "../../General/gen_ml/ml.h"
#include "../../Library/ml_pmp/pmp.h"
#include "AndroidDevice.h"
#include <strsafe.h>
#include <shlwapi.h>
BOOL RecursiveCreateDirectory(wchar_t* buf1);
__int64 fileSize(wchar_t * filename);
bool supportedFormat(wchar_t * file, wchar_t * supportedFormats);
DeviceType detectDeviceType(wchar_t drive);
void removebadchars(wchar_t *s);
wchar_t * FixReplacementVars(wchar_t *str, int str_size, Device * dev, songid_t song);
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);
}
}
__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;
}
// RecursiveCreateDirectory: creates all non-existent folders in a path
BOOL RecursiveCreateDirectory(wchar_t* buf1) {
wchar_t *p=buf1;
int errors = 0;
if (*p) {
p = PathSkipRoot(buf1);
if (!p) return true ;
wchar_t ch='c';
while (ch) {
while (p && *p != '\\' && *p) p = CharNext(p);
ch = (p ? *p : 0);
if (p) *p = 0;
int pp = (int)wcslen(buf1)-1;
while(buf1[pp] == '.' || buf1[pp] == ' ' ||
(buf1[pp] == '\\' && (buf1[pp-1] == '.' || buf1[pp-1] == ' ' || buf1[pp-1] == '/')) ||
buf1[pp] == '/' && buf1)
{
if(buf1[pp] == '\\')
{
buf1[pp-1] = '_';
pp -= 2;
} else {
buf1[pp] = '_';
pp--;
}
}
WIN32_FIND_DATA fd = {0};
// Avoid a "There is no disk in the drive" error box on empty removable drives
UINT prevErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
HANDLE h = FindFirstFile(buf1,&fd);
SetErrorMode(prevErrorMode);
if (h == INVALID_HANDLE_VALUE)
{
if (!CreateDirectory(buf1,NULL)) errors++;
} else {
FindClose(h);
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) errors++;
}
if (p) *p++ = ch;
}
}
return errors != 0;
}
bool supportedFormat(wchar_t * file, wchar_t * supportedFormats) {
wchar_t * ext = wcsrchr(file,'.');
if(!ext) return false;
ext++;
wchar_t * p = supportedFormats;
while(p && *p) {
bool ret=false;
wchar_t * np = wcschr(p,L';');
if(np) *np = 0;
if(!_wcsicmp(ext,p)) ret=true;
if(np) { *np = L';'; p=np+1; }
else return ret;
if(ret) return true;
}
return false;
}
// FixReplacementVars: replaces <Artist>, <Title>, <Album>, and #, ##, ##, with appropriate data
// DOES NOT add a file extention!!
wchar_t * fixReplacementVars(wchar_t *str, int str_size, Device * dev, songid_t song)
{
#define ADD_STR(x) { x(song,outp,str_size-1-(outp-str)); removebadchars(outp); while (outp && *outp) outp++; }
#define ADD_STR_U(x) { x(song,outp,str_size-1-(outp-str)); removebadchars(outp); while (outp && *outp) { *outp=towupper(*outp); outp++; } }
#define ADD_STR_L(x) { x(song,outp,str_size-1-(outp-str)); removebadchars(outp); while (outp && *outp) { *outp=towlower(*outp); outp++; } }
wchar_t tmpsrc[4096] = {0};
lstrcpyn(tmpsrc,str,sizeof(tmpsrc)/sizeof(wchar_t)); //lstrcpyn is nice enough to make sure it's null terminated.
wchar_t *inp = tmpsrc;
wchar_t *outp = str;
int slash = 0;
while (inp && *inp && outp-str < str_size-2)
{
if (*inp == L'<')
{
if (!wcsncmp(inp,L"<TITLE>",7))
{
ADD_STR_U(dev->getTrackTitle);
inp+=7;
}
else if (!wcsncmp(inp,L"<title>",7))
{
ADD_STR_L(dev->getTrackTitle);
inp+=7;
}
else if (!_wcsnicmp(inp,L"<Title>",7))
{
ADD_STR(dev->getTrackTitle);
inp+=7;
}
else if (!wcsncmp(inp,L"<ALBUM>",7))
{
ADD_STR_U(dev->getTrackAlbum);
inp+=7;
}
else if (!wcsncmp(inp,L"<album>",7))
{
ADD_STR_L(dev->getTrackAlbum);
inp+=7;
}
else if (!_wcsnicmp(inp,L"<Album>",7))
{
ADD_STR(dev->getTrackAlbum);
inp+=7;
}
else if (!wcsncmp(inp,L"<GENRE>",7))
{
ADD_STR_U(dev->getTrackGenre);
inp+=7;
}
else if (!wcsncmp(inp,L"<genre>",7))
{
ADD_STR_L(dev->getTrackGenre);
inp+=7;
}
else if (!_wcsnicmp(inp,L"<Genre>",7))
{
ADD_STR(dev->getTrackGenre);
inp+=7;
}
else if (!wcsncmp(inp,L"<ARTIST>",8))
{
ADD_STR_U(dev->getTrackArtist);
inp+=8;
}
else if (!wcsncmp(inp,L"<artist>",8))
{
ADD_STR_L(dev->getTrackArtist);
inp+=8;
}
else if (!_wcsnicmp(inp,L"<Artist>",8))
{
ADD_STR(dev->getTrackArtist);
inp+=8;
}
else if (!wcsncmp(inp,L"<ALBUMARTIST>",13))
{
wchar_t temp[128] = {0};
dev->getTrackAlbumArtist(song, temp, 128);
if (temp[0] == 0)
dev->getTrackArtist(song, temp, 128);
lstrcpyn(outp,temp,str_size-1-(outp-str));
removebadchars(outp);
while (outp && *outp) { *outp=towupper(*outp); outp++; }
inp+=13;
}
else if (!wcsncmp(inp,L"<albumartist>",13))
{
wchar_t temp[128] = {0};
dev->getTrackAlbumArtist(song, temp, 128);
if (temp[0] == 0)
dev->getTrackArtist(song, temp, 128);
lstrcpyn(outp,temp,str_size-1-(outp-str));
removebadchars(outp);
while (outp && *outp) { *outp=towlower(*outp); outp++; }
inp+=13;
}
else if (!_wcsnicmp(inp,L"<Albumartist>",13))
{
wchar_t temp[128] = {0};
dev->getTrackAlbumArtist(song, temp, 128);
if (temp[0] == 0)
dev->getTrackArtist(song, temp, 128);
lstrcpyn(outp,temp, (int)str_size-1-(outp-str));
removebadchars(outp);
while (outp && *outp) outp++;
inp+=13;
}
else if (!_wcsnicmp(inp,L"<year>",6))
{
wchar_t year[64] = {0};
int y = dev->getTrackYear(song);
if (y) StringCchPrintf(year, ARRAYSIZE(year), L"%d", y);
lstrcpyn(outp,year, (int)str_size-1-(outp-str)); while (outp && *outp) outp++;
inp+=6;
}
else if (!_wcsnicmp(inp,L"<disc>",6))
{
wchar_t disc[16] = {0};
int d = dev->getTrackDiscNum(song);
if (d) StringCchPrintf(disc, ARRAYSIZE(disc), L"%d", d);
lstrcpyn(outp,disc, (int)str_size-1-(outp-str)); while (outp && *outp) outp++;
inp+=6;
}
else if (!_wcsnicmp(inp,L"<filename>",10))
{
wchar_t tfn[MAX_PATH], *ext, *fn;
StringCchCopy(tfn,MAX_PATH,((AndroidSong*)song)->filename);
ext = wcsrchr(tfn, L'.');
*ext = 0; //kill extension since its added later
fn = wcsrchr(tfn, L'\\');
fn++;
lstrcpyn(outp,fn, (int)str_size-1-(outp-str));
while (outp && *outp) outp++;
inp+=10;
}
else
{
// use this to skip over unknown tags
while (inp && *inp && *inp != L'>') inp++;
if (inp) inp++;
}
}
else if (*inp == L'#')
{
int nd=0;
wchar_t tmp[64] = {0};
while (inp && *inp == L'#') nd++,inp++;
int track = dev->getTrackTrackNum(song);
if (!track)
{
while (inp && *inp == L' ') inp++;
while (inp && *inp == L'\\') inp++;
if (inp && (*inp == L'-' || *inp == L'.' || *inp == L'_')) // separator
{
inp++;
while (inp && *inp == L' ') inp++;
}
}
else
{
if (nd > 1)
{
wchar_t tmp2[32] = {0};
if (nd > 5) nd=5;
StringCchPrintf(tmp2, ARRAYSIZE(tmp2), L"%%%02dd",nd);
StringCchPrintf(tmp, ARRAYSIZE(tmp), tmp2,track);
}
else StringCchPrintf(tmp, ARRAYSIZE(tmp), L"%d",track);
}
lstrcpyn(outp,tmp, (int)str_size-1-(outp-str)); while (outp && *outp) outp++;
}
else
{
if (*inp == L'\\') slash += 1;
*outp++=*inp++;
}
}
if (outp) *outp = 0;
// if we end up with something like U:\\\ then this
// will set it to be just <filename> so it'll not
// end up making a load of bad files e.g. U:\.mp3
int out_len = lstrlen(str);
if (out_len)
{
if (out_len - 2 == slash)
{
outp = str + 3;
wchar_t tfn[MAX_PATH], *ext, *fn;
StringCchCopy(tfn,MAX_PATH,((AndroidSong*)song)->filename);
ext = wcsrchr(tfn, L'.');
*ext = 0; //kill extension since its added later
fn = wcsrchr(tfn, L'\\');
fn++;
lstrcpyn(outp,fn, (int)str_size-1-(outp-str));
while (outp && *outp) outp++;
if (outp) *outp = 0;
}
}
inp=str;
outp=str;
wchar_t lastc=0;
while (inp && *inp)
{
wchar_t ch=*inp++;
if (ch == L'\t') ch=L' ';
if (ch == L' ' && (lastc == L' ' || lastc == L'\\' || lastc == L'/')) continue; // ignore space after slash, or another space
if ((ch == L'\\' || ch == L'/') && lastc == L' ') outp--; // if we have a space then slash, back up to write the slash where the space was
*outp++=ch;
lastc=ch;
}
if (outp) *outp=0;
#undef ADD_STR
#undef ADD_STR_L
#undef ADD_STR_U
return str;
}
@@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../../../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,72,0,0
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp Portable Device Plug-in"
VALUE "FileVersion", "1,72,0,0"
VALUE "InternalName", "Nullsoft Android Device"
VALUE "LegalCopyright", "Copyright © 2010-2023 Winamp SA"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "pmp_android.dll"
VALUE "ProductName", "Winamp"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
@@ -0,0 +1,149 @@
#include <windows.h>
#include <stddef.h> // for offsetof
#include <winioctl.h>
#include <strsafe.h>
typedef struct {
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
PVOID DataBuffer;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
typedef struct {
SCSI_PASS_THROUGH_DIRECT spt;
ULONG Filler;
UCHAR ucSenseBuf[32];
} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
#define IOCTL_SCSI_BASE 0x00000004
/*
* constants for DataIn member of SCSI_PASS_THROUGH* structures
*/
#define SCSI_IOCTL_DATA_OUT 0
#define SCSI_IOCTL_DATA_IN 1
#define SCSI_IOCTL_DATA_UNSPECIFIED 2
/*
* Standard IOCTL define
*/
#define CTL_CODE( DevType, Function, Method, Access ) ( \
((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
#define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
#define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS
static bool scsi_inquiry(HANDLE deviceHandle, UCHAR page, UCHAR *inqbuf, size_t &buf_len)
{
char buf[2048] = {0};
BOOL status;
PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER pswb;
DWORD length=0, returned=0;
/*
* Get the drive inquiry data
*/
ZeroMemory( &buf, 2048 );
ZeroMemory( inqbuf, buf_len );
pswb = (PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)buf;
pswb->spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
pswb->spt.CdbLength = 6;
pswb->spt.SenseInfoLength = 32;
pswb->spt.DataIn = SCSI_IOCTL_DATA_IN;
pswb->spt.DataTransferLength = buf_len;
pswb->spt.TimeOutValue = 2;
pswb->spt.DataBuffer = inqbuf;
pswb->spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
pswb->spt.Cdb[0] = 0x12;
pswb->spt.Cdb[1] = 0x1;
pswb->spt.Cdb[2] = page;
pswb->spt.Cdb[4] = (UCHAR)buf_len;
length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
status = DeviceIoControl( deviceHandle,
IOCTL_SCSI_PASS_THROUGH_DIRECT,
pswb,
length,
pswb,
length,
&returned,
NULL );
if (status && returned >3)
{
buf_len=returned;
return true;
}
else
{
buf_len=0;
return false;
}
}
static bool AddPagetoXML(HANDLE dev, char *&dest, size_t &destlen, UCHAR page)
{
UCHAR buf[256] = {0};
size_t buflen=255;
if (scsi_inquiry(dev, page, buf, buflen))
{
size_t len = buf[3];
StringCchCopyNExA(dest, destlen, (char *)buf+4, len, &dest, &destlen, 0);
return true;
}
return false;
}
static bool BuildXML(HANDLE dev, char *xml, size_t xmllen)
{
*xml=0;
UCHAR pages[255] = {0};
size_t pageslen=255;
if (scsi_inquiry(dev, 0xc0, pages, pageslen) && pageslen>3)
{
unsigned char numPages=pages[3];
if (numPages+4 <= 255)
{
for (int i=0;i<numPages;i++)
{
if (!AddPagetoXML(dev, xml, xmllen, pages[i+4]))
return false;
}
}
}
return true;
}
bool ParseSysInfoXML(wchar_t drive_letter, char * xml, int xmllen)
{
wchar_t fn[MAX_PATH] = {0};
StringCchPrintf(fn, MAX_PATH, L"\\\\.\\%c:", drive_letter);
HANDLE hfile = CreateFileW(fn, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (hfile != INVALID_HANDLE_VALUE)
{
bool ret = BuildXML(hfile, xml, xmllen);
CloseHandle(hfile);
return ret;
}
return false;
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef NULLSOFT_PMP_IPOD_API_H
#define NULLSOFT_PMP_IPOD_API_H
#include <api/memmgr/api_memmgr.h>
extern api_memmgr *memmgr;
#define WASABI_API_MEMMGR memmgr
#include "../Agave/AlbumArt/api_albumart.h"
extern api_albumart *albumArtApi;
#define AGAVE_API_ALBUMART albumArtApi
#include "../Agave/Config/api_config.h"
extern api_config *agaveConfigApi;
#define AGAVE_API_CONFIG agaveConfigApi
#include "../Agave/Language/api_language.h"
#include "../nu/threadpool/api_threadpool.h"
extern api_threadpool *threadPoolApi;
#define WASABI_API_THREADPOOL threadPoolApi
#include <api/application/api_application.h>
extern api_application *applicationApi;
#define WASABI_API_APP applicationApi
#include "../devices/api_devicemanager.h"
extern api_devicemanager *deviceManagerApi;
#define AGAVE_API_DEVICEMANAGER deviceManagerApi
#endif
@@ -0,0 +1,343 @@
#include "api.h"
#include "./deviceprovider.h"
#include "../devices/api_devicemanager.h"
extern PMPDevicePlugin plugin;
bool ConnectDrive(wchar_t drive, bool connect);
static size_t tlsIndex = (size_t)-1;
static BOOL
DiscoveryProvider_RegisterCancelSwitch(BOOL *cancelSwitch)
{
if ((size_t)-1 != tlsIndex &&
NULL != WASABI_API_APP)
{
WASABI_API_APP->SetThreadStorage(tlsIndex, cancelSwitch);
return TRUE;
}
return FALSE;
}
static BOOL
DiscoveryProvider_GetCancelSwitchOn()
{
if ((size_t)-1 != tlsIndex &&
NULL != WASABI_API_APP)
{
BOOL *cancelSwitch = (BOOL*)WASABI_API_APP->GetThreadStorage(tlsIndex);
if (NULL != cancelSwitch &&
FALSE != *cancelSwitch)
{
return TRUE;
}
}
return FALSE;
}
static void
DeviceProvider_DriverEnumCb(wchar_t drive, unsigned int type)
{
if (DRIVE_REMOVABLE == type &&
FALSE == DiscoveryProvider_GetCancelSwitchOn())
{
ConnectDrive(drive,true);
}
}
DeviceProvider::DeviceProvider()
: ref(1), activity(0), manager(NULL), readyEvent(NULL), cancelDiscovery(FALSE)
{
InitializeCriticalSection(&lock);
enumerator = (ENUMDRIVES)SendMessageW(plugin.hwndPortablesParent,
WM_PMP_IPC, 0, PMP_IPC_ENUM_ACTIVE_DRIVES);
}
DeviceProvider::~DeviceProvider()
{
CancelDiscovery();
if (NULL != readyEvent)
CloseHandle(readyEvent);
DeleteCriticalSection(&lock);
}
HRESULT DeviceProvider::CreateInstance(DeviceProvider **instance)
{
if (NULL == instance)
return E_POINTER;
*instance = new DeviceProvider();
if (NULL == *instance)
return E_OUTOFMEMORY;
return S_OK;
}
size_t DeviceProvider::AddRef()
{
return InterlockedIncrement((LONG*)&ref);
}
size_t DeviceProvider::Release()
{
if (0 == ref)
return ref;
LONG r = InterlockedDecrement((LONG*)&ref);
if (0 == r)
delete(this);
return r;
}
int DeviceProvider::QueryInterface(GUID interface_guid, void **object)
{
if (NULL == object)
return E_POINTER;
if (IsEqualIID(interface_guid, IFC_DeviceProvider))
*object = static_cast<ifc_deviceprovider*>(this);
else
{
*object = NULL;
return E_NOINTERFACE;
}
if (NULL == *object)
return E_UNEXPECTED;
AddRef();
return S_OK;
}
void DeviceProvider::Lock()
{
EnterCriticalSection(&lock);
}
void DeviceProvider::Unlock()
{
LeaveCriticalSection(&lock);
}
DWORD DeviceProvider::DiscoveryThread()
{
IncrementActivity();
if (NULL != enumerator &&
FALSE == cancelDiscovery)
{
DiscoveryProvider_RegisterCancelSwitch(&cancelDiscovery);
enumerator(DeviceProvider_DriverEnumCb);
DiscoveryProvider_RegisterCancelSwitch(NULL);
}
DecrementActivity();
Lock();
if (NULL != readyEvent)
SetEvent(readyEvent);
Unlock();
return 0;
}
static int DeviceProvider_DiscoveryThreadStarter(HANDLE handle, void *user, intptr_t id)
{
DeviceProvider *self;
DWORD result;
self = (DeviceProvider*)user;
if (NULL != self)
result = self->DiscoveryThread();
else
result = -2;
return result;
}
HRESULT DeviceProvider::BeginDiscovery(api_devicemanager *manager)
{
HRESULT hr;
if (NULL == enumerator)
return E_UNEXPECTED;
Lock();
if (NULL != readyEvent &&
WAIT_TIMEOUT == WaitForSingleObject(readyEvent, 0))
{
hr = E_PENDING;
}
else
{
hr = S_OK;
if (NULL == readyEvent)
{
readyEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
if (NULL == readyEvent)
hr = E_FAIL;
}
if ((size_t)-1 == tlsIndex &&
NULL != WASABI_API_APP)
{
tlsIndex = WASABI_API_APP->AllocateThreadStorage();
}
if (SUCCEEDED(hr))
{
cancelDiscovery = FALSE;
ResetEvent(readyEvent);
if (0 != WASABI_API_THREADPOOL->RunFunction(0, DeviceProvider_DiscoveryThreadStarter,
this, 0, api_threadpool::FLAG_LONG_EXECUTION))
{
SetEvent(readyEvent);
hr = E_FAIL;
}
}
}
Unlock();
return hr;
}
HRESULT DeviceProvider::CancelDiscovery()
{
HRESULT hr;
hr = S_FALSE;
Lock();
if (NULL != readyEvent)
{
cancelDiscovery = TRUE;
if (WAIT_OBJECT_0 == WaitForSingleObject(readyEvent, 0))
hr = S_OK;
cancelDiscovery = FALSE;
}
Unlock();
return hr;
}
HRESULT DeviceProvider::GetActive()
{
HRESULT hr;
Lock();
if (0 != activity)
hr = S_OK;
else
hr = S_FALSE;
Unlock();
return hr;
}
HRESULT DeviceProvider::Register(api_devicemanager *manager)
{
HRESULT hr;
if (NULL != this->manager)
return E_UNEXPECTED;
if (NULL == manager)
return E_POINTER;
hr = manager->RegisterProvider(this);
if (SUCCEEDED(hr))
{
this->manager = manager;
manager->AddRef();
}
return hr;
}
HRESULT DeviceProvider::Unregister()
{
HRESULT hr;
if (NULL == manager)
return E_UNEXPECTED;
hr = manager->UnregisterProvider(this);
manager->Release();
manager = NULL;
return hr;
}
size_t DeviceProvider::IncrementActivity()
{
size_t a;
Lock();
activity++;
if (1 == activity &&
NULL != manager)
{
manager->SetProviderActive(this, TRUE);
}
a = activity;
Unlock();
return a;
}
size_t DeviceProvider::DecrementActivity()
{
size_t a;
Lock();
if (0 != activity)
{
activity--;
if (0 == activity &&
NULL != manager)
{
manager->SetProviderActive(this, FALSE);
}
}
a = activity;
Unlock();
return a;
}
#define CBCLASS DeviceProvider
START_DISPATCH;
CB(ADDREF, AddRef)
CB(RELEASE, Release)
CB(QUERYINTERFACE, QueryInterface)
CB(API_BEGINDISCOVERY, BeginDiscovery)
CB(API_CANCELDISCOVERY, CancelDiscovery)
CB(API_GETACTIVE, GetActive)
END_DISPATCH;
#undef CBCLASS
@@ -0,0 +1,50 @@
#pragma once
#include <wtypes.h>
#include "../devices/ifc_deviceprovider.h"
#include "..\..\Library\ml_pmp/pmp.h"
class DeviceProvider : public ifc_deviceprovider
{
protected:
DeviceProvider();
~DeviceProvider();
public:
static HRESULT CreateInstance(DeviceProvider **instance);
public:
/* Dispatchable */
size_t AddRef();
size_t Release();
int QueryInterface(GUID interface_guid, void **object);
/* ifc_deviceprovider */
HRESULT BeginDiscovery(api_devicemanager *manager);
HRESULT CancelDiscovery();
HRESULT GetActive();
public:
HRESULT Register(api_devicemanager *manager);
HRESULT Unregister();
size_t IncrementActivity();
size_t DecrementActivity();
private:
void Lock();
void Unlock();
DWORD DiscoveryThread();
friend static int DeviceProvider_DiscoveryThreadStarter(HANDLE handle, void *user_data, intptr_t id);
protected:
size_t ref;
size_t activity;
CRITICAL_SECTION lock;
api_devicemanager *manager;
ENUMDRIVES enumerator;
HANDLE readyEvent;
BOOL cancelDiscovery;
protected:
RECVS_DISPATCH;
};
+357
View File
@@ -0,0 +1,357 @@
// this file almost totally copied from MSDN
#include <windows.h>
#include <stdio.h>
#include <winioctl.h>
#define LOCK_TIMEOUT 3000 // 10 Seconds
#define LOCK_RETRIES 20
#if 1 // old way
static HANDLE OpenVolume(TCHAR cDriveLetter)
{
HANDLE hVolume;
UINT uDriveType;
wchar_t szVolumeName[8] = {0};
wchar_t szRootName[5] = {0};
DWORD dwAccessFlags = 0;
cDriveLetter &= ~0x20; // capitalize
wsprintf(szRootName, L"%c:\\", cDriveLetter);
uDriveType = GetDriveType(szRootName);
switch(uDriveType) {
case DRIVE_REMOVABLE:
dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
break;
case DRIVE_CDROM:
dwAccessFlags = GENERIC_READ;
break;
default:
printf("Cannot eject. Drive type is incorrect.\n");
return INVALID_HANDLE_VALUE;
}
wsprintf(szVolumeName, L"\\\\.\\%c:", cDriveLetter);
hVolume = CreateFile( szVolumeName,
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if (hVolume == INVALID_HANDLE_VALUE)
printf("CreateFile error %d\n", GetLastError());
return hVolume;
}
static BOOL CloseVolume(HANDLE hVolume)
{
return CloseHandle(hVolume);
}
static BOOL LockVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
DWORD dwSleepAmount;
int nTryCount;
dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;
// Do this in a loop until a timeout period has expired
for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
if (DeviceIoControl(hVolume,
FSCTL_LOCK_VOLUME,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL))
return TRUE;
Sleep(dwSleepAmount);
}
return FALSE;
}
static BOOL DismountVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
return DeviceIoControl( hVolume,
FSCTL_DISMOUNT_VOLUME,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL);
}
static BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
{
DWORD dwBytesReturned;
PREVENT_MEDIA_REMOVAL PMRBuffer;
PMRBuffer.PreventMediaRemoval = fPreventRemoval;
return DeviceIoControl( hVolume,
IOCTL_STORAGE_MEDIA_REMOVAL,
&PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
NULL, 0,
&dwBytesReturned,
NULL);
}
static int AutoEjectVolume(HANDLE hVolume)
{
DWORD dwBytesReturned;
return DeviceIoControl( hVolume,
IOCTL_STORAGE_EJECT_MEDIA,
NULL, 0,
NULL, 0,
&dwBytesReturned,
NULL);
}
BOOL EjectVolume(TCHAR cDriveLetter)
{
HANDLE hVolume;
BOOL fAutoEject = FALSE;
hVolume = OpenVolume(cDriveLetter);
if (hVolume == INVALID_HANDLE_VALUE)
return FALSE;
// Lock and dismount the volume.
if (LockVolume(hVolume) && DismountVolume(hVolume)) {
// Set prevent removal to false and eject the volume.
if (PreventRemovalOfVolume(hVolume, FALSE) && AutoEjectVolume(hVolume))
fAutoEject = TRUE;
}
// Close the volume so other processes can use the drive.
if (!CloseVolume(hVolume))
return FALSE;
if (fAutoEject) return TRUE;
else return FALSE;
}
#else
#include <stdio.h>
#include <windows.h>
#include <Setupapi.h>
#include <winioctl.h>
#include <winioctl.h>
#include <cfgmgr32.h>
#pragma comment(lib, "setupapi.lib")
//-------------------------------------------------
//----------------------------------------------------------------------
// returns the device instance handle of a storage volume or 0 on error
//----------------------------------------------------------------------
static DEVINST GetDrivesDevInstByDeviceNumber(long DeviceNumber, UINT DriveType, const wchar_t* szDosDeviceName)
{
bool IsFloppy = (wcsstr(szDosDeviceName, L"\\Floppy") != NULL); // who knows a better way?
GUID* guid;
switch (DriveType) {
case DRIVE_REMOVABLE:
if ( IsFloppy ) {
guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY;
} else {
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
}
break;
case DRIVE_FIXED:
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
break;
case DRIVE_CDROM:
guid = (GUID*)&GUID_DEVINTERFACE_CDROM;
break;
default:
return 0;
}
// Get device interface info set handle for all devices attached to system
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) {
return 0;
}
// Retrieve a context structure for a device interface of a device information set
DWORD dwIndex = 0;
long res;
BYTE Buf[1024] = {0};
PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
SP_DEVICE_INTERFACE_DATA spdid;
SP_DEVINFO_DATA spdd;
DWORD dwSize;
spdid.cbSize = sizeof(spdid);
while ( true ) {
res = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &spdid);
if ( !res ) {
break;
}
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL); // check the buffer size
if ( dwSize!=0 && dwSize<=sizeof(Buf) ) {
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
ZeroMemory(&spdd, sizeof(spdd));
spdd.cbSize = sizeof(spdd);
long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, pspdidd, dwSize, &dwSize, &spdd);
if ( res ) {
// in case you are interested in the USB serial number:
// the device id string contains the serial number if the device has one,
// otherwise a generated id that contains the '&' char...
/*
DEVINST DevInstParent = 0;
CM_Get_Parent(&DevInstParent, spdd.DevInst, 0);
char szDeviceIdString[MAX_PATH] = {0};
CM_Get_Device_ID(DevInstParent, szDeviceIdString, MAX_PATH, 0);
printf("DeviceId=%s\n", szDeviceIdString);
*/
// open the disk or cdrom or floppy
HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if ( hDrive != INVALID_HANDLE_VALUE ) {
// get its device number
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
res = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if ( res ) {
if ( DeviceNumber == (long)sdn.DeviceNumber ) { // match the given device number with the one of the current device
CloseHandle(hDrive);
SetupDiDestroyDeviceInfoList(hDevInfo);
return spdd.DevInst;
}
}
CloseHandle(hDrive);
}
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return 0;
}
//-------------------------------------------------
//-------------------------------------------------
BOOL EjectVolume(TCHAR DriveLetter)
{
DriveLetter &= ~0x20; // uppercase
if ( DriveLetter < 'A' || DriveLetter > 'Z' ) {
return FALSE;
}
wchar_t szRootPath[] = L"X:\\"; // "X:\" -> for GetDriveType
szRootPath[0] = DriveLetter;
wchar_t szDevicePath[] = L"X:"; // "X:" -> for QueryDosDevice
szDevicePath[0] = DriveLetter;
wchar_t szVolumeAccessPath[] = L"\\\\.\\X:"; // "\\.\X:" -> to open the volume
szVolumeAccessPath[4] = DriveLetter;
long DeviceNumber = -1;
// open the storage volume
HANDLE hVolume = CreateFileW(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hVolume == INVALID_HANDLE_VALUE) {
return FALSE;
}
// get the volume's device number
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if ( res ) {
DeviceNumber = sdn.DeviceNumber;
}
CloseHandle(hVolume);
if ( DeviceNumber == -1 ) {
return FALSE;
}
// get the drive type which is required to match the device numbers correctely
UINT DriveType = GetDriveType(szRootPath);
// get the dos device name (like \device\floppy0) to decide if it's a floppy or not - who knows a better way?
wchar_t szDosDeviceName[MAX_PATH] = {0};
res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH);
if ( !res ) {
return FALSE;
}
// get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number
DEVINST DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, DriveType, szDosDeviceName);
if ( DevInst == 0 ) {
return FALSE;
}
PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
wchar_t VetoNameW[MAX_PATH] = {0};
bool bSuccess = false;
// get drives's parent, e.g. the USB bridge, the SATA port, an IDE channel with two drives!
DEVINST DevInstParent = 0;
res = CM_Get_Parent(&DevInstParent, DevInst, 0);
for ( long tries=1; tries<=3; tries++ ) { // sometimes we need some tries...
VetoNameW[0] = 0;
// CM_Query_And_Remove_SubTree doesn't work for restricted users
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, CM_REMOVE_NO_RESTART); // CM_Query_And_Remove_SubTreeA is not implemented under W2K!
//res = CM_Query_And_Remove_SubTreeW(DevInstParent, NULL, NULL, 0, CM_REMOVE_NO_RESTART); // with messagebox (W2K, Vista) or balloon (XP)
res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0);
//res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP)
bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown);
if ( bSuccess ) {
break;
}
Sleep(500); // required to give the next tries a chance!
}
if ( bSuccess ) {
printf("Success\n\n");
return TRUE;
}
printf("failed\n");
printf("Result=0x%2X\n", res);
if ( VetoNameW[0] ) {
printf("VetoName=%ws)\n\n", VetoNameW);
}
return FALSE;
}
//-----------------------------------------------------------
#endif
@@ -0,0 +1,69 @@
#include "api.h"
#include <windows.h>
#include <stdio.h>
#include <wchar.h>
#include "resource.h"
#include <strsafe.h>
typedef struct CopyData
{
void * callbackContext;
void (*callback)(void * callbackContext, wchar_t * status);
} CopyData;
DWORD CALLBACK CopyToIpodProgressRoutine(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred,
LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred,
DWORD dwStreamNumber,
DWORD dwCallbackReason,
HANDLE hSourceFile, HANDLE hDestinationFile,
LPVOID lpData)
{
CopyData *inst = (CopyData *)lpData;
if (inst && inst->callback)
{
wchar_t status[100] = {0};
wchar_t langtemp[100] = {0};
StringCbPrintf(status, sizeof(status), WASABI_API_LNGSTRINGW_BUF(IDS_TRANSFERRING_PERCENT, langtemp, 100), (int)(100ULL * TotalBytesTransferred.QuadPart / (TotalFileSize.QuadPart)));
inst->callback(inst->callbackContext,status);
}
return PROGRESS_CONTINUE;
}
int CopyFile(const wchar_t *infile, const wchar_t *outfile, void * callbackContext, void (*callback)(void * callbackContext, wchar_t * status), int * killswitch)
{
wchar_t langtemp[100] = {0};
CopyData c;
c.callback = callback;
c.callbackContext = callbackContext;
if (CopyFileEx(infile, outfile, CopyToIpodProgressRoutine, &c, killswitch,0))
{
if (callback)
{
callback(callbackContext, WASABI_API_LNGSTRINGW_BUF(IDS_DONE, langtemp, 100));
}
return 0;
}
else
{
switch(GetLastError())
{
case ERROR_REQUEST_ABORTED:
DeleteFile(outfile);
if (callback)
{
callback(callbackContext, WASABI_API_LNGSTRINGW_BUF(IDS_CANCELLED, langtemp, 100));
}
default:
if (callback)
{
callback(callbackContext, WASABI_API_LNGSTRINGW_BUF(IDS_TRANSFER_FAILED, langtemp, 100));
}
}
return -1;
}
}
+154
View File
@@ -0,0 +1,154 @@
#include "sha1.h"
#include <memory.h>
#include <algorithm>
unsigned char invTable[256] = {
0x74, 0x85, 0x96, 0xA7, 0xB8, 0xC9, 0xDA, 0xEB, 0xFC, 0x0D, 0x1E, 0x2F, 0x40, 0x51, 0x62, 0x73,
0x84, 0x95, 0xA6, 0xB7, 0xC8, 0xD9, 0xEA, 0xFB, 0x0C, 0x1D, 0x2E, 0x3F, 0x50, 0x61, 0x72, 0x83,
0x94, 0xA5, 0xB6, 0xC7, 0xD8, 0xE9, 0xFA, 0x0B, 0x1C, 0x2D, 0x3E, 0x4F, 0x60, 0x71, 0x82, 0x93,
0xA4, 0xB5, 0xC6, 0xD7, 0xE8, 0xF9, 0x0A, 0x1B, 0x2C, 0x3D, 0x4E, 0x5F, 0x70, 0x81, 0x92, 0xA3,
0xB4, 0xC5, 0xD6, 0xE7, 0xF8, 0x09, 0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F, 0x80, 0x91, 0xA2, 0xB3,
0xC4, 0xD5, 0xE6, 0xF7, 0x08, 0x19, 0x2A, 0x3B, 0x4C, 0x5D, 0x6E, 0x7F, 0x90, 0xA1, 0xB2, 0xC3,
0xD4, 0xE5, 0xF6, 0x07, 0x18, 0x29, 0x3A, 0x4B, 0x5C, 0x6D, 0x7E, 0x8F, 0xA0, 0xB1, 0xC2, 0xD3,
0xE4, 0xF5, 0x06, 0x17, 0x28, 0x39, 0x4A, 0x5B, 0x6C, 0x7D, 0x8E, 0x9F, 0xB0, 0xC1, 0xD2, 0xE3,
0xF4, 0x05, 0x16, 0x27, 0x38, 0x49, 0x5A, 0x6B, 0x7C, 0x8D, 0x9E, 0xAF, 0xC0, 0xD1, 0xE2, 0xF3,
0x04, 0x15, 0x26, 0x37, 0x48, 0x59, 0x6A, 0x7B, 0x8C, 0x9D, 0xAE, 0xBF, 0xD0, 0xE1, 0xF2, 0x03,
0x14, 0x25, 0x36, 0x47, 0x58, 0x69, 0x7A, 0x8B, 0x9C, 0xAD, 0xBE, 0xCF, 0xE0, 0xF1, 0x02, 0x13,
0x24, 0x35, 0x46, 0x57, 0x68, 0x79, 0x8A, 0x9B, 0xAC, 0xBD, 0xCE, 0xDF, 0xF0, 0x01, 0x12, 0x23,
0x34, 0x45, 0x56, 0x67, 0x78, 0x89, 0x9A, 0xAB, 0xBC, 0xCD, 0xDE, 0xEF, 0x00, 0x11, 0x22, 0x33,
0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x10, 0x21, 0x32, 0x43,
0x54, 0x65, 0x76, 0x87, 0x98, 0xA9, 0xBA, 0xCB, 0xDC, 0xED, 0xFE, 0x0F, 0x20, 0x31, 0x42, 0x53,
0x64, 0x75, 0x86, 0x97, 0xA8, 0xB9, 0xCA, 0xDB, 0xEC, 0xFD, 0x0E, 0x1F, 0x30, 0x41, 0x52, 0x63
};
unsigned char table1[256] = {
0x3A, 0x3F, 0x3E, 0x72, 0xBD, 0xA2, 0xD6, 0xB4, 0x63, 0xC0, 0x6E, 0x62, 0x59, 0x1E, 0xE2, 0x71,
0xB5, 0x0D, 0xE8, 0x0C, 0x25, 0x38, 0xCE, 0x23, 0x7C, 0xB7, 0xAD, 0x16, 0xDF, 0x47, 0x3D, 0xB3,
0x7E, 0x8C, 0xAA, 0x61, 0x31, 0x66, 0xBE, 0x4F, 0x97, 0x14, 0x54, 0xF0, 0x70, 0xEB, 0x30, 0xC4,
0x27, 0x4E, 0xFA, 0x1A, 0x2B, 0x11, 0xF4, 0x45, 0x8E, 0x5D, 0x73, 0xED, 0x22, 0x2E, 0x7D, 0xA4,
0x28, 0xDA, 0x2F, 0xC5, 0x92, 0x09, 0x05, 0x13, 0x9D, 0x32, 0x51, 0x4A, 0xC8, 0xBA, 0x96, 0xA7,
0x6A, 0x50, 0xF3, 0xBC, 0x93, 0xBF, 0xB0, 0xD2, 0xD5, 0x82, 0x19, 0x98, 0x35, 0xCF, 0x6B, 0xB6,
0x83, 0x56, 0x15, 0xF2, 0x9A, 0x9C, 0xCA, 0x74, 0x34, 0x58, 0x8D, 0xA6, 0x03, 0xFF, 0x46, 0x7B,
0xD0, 0x7A, 0x33, 0x76, 0xDD, 0xAC, 0xCB, 0x24, 0x7F, 0xB1, 0x85, 0x60, 0xC3, 0x26, 0x8A, 0x1D,
0x1C, 0x8F, 0x2A, 0xEF, 0x06, 0xDE, 0x67, 0x5E, 0xE7, 0xAE, 0xD9, 0xCC, 0x07, 0x6C, 0xF8, 0x0A,
0xD3, 0x40, 0x36, 0x1F, 0x2D, 0x95, 0x43, 0xDB, 0x01, 0x89, 0x4B, 0xF7, 0xB9, 0x39, 0xC2, 0x52,
0x53, 0xFD, 0x65, 0xF5, 0x68, 0xC1, 0xC7, 0x9F, 0x4D, 0xEA, 0xAF, 0x6D, 0x10, 0x44, 0x87, 0xD8,
0xEE, 0x1B, 0xFE, 0x3C, 0xDC, 0x84, 0x69, 0x48, 0x6F, 0xD1, 0x57, 0x55, 0xD4, 0xA5, 0x49, 0x5B,
0xE5, 0x0B, 0x94, 0xC9, 0x5F, 0xE1, 0x17, 0x81, 0xBB, 0xEC, 0xD7, 0xC6, 0x02, 0x4C, 0x42, 0x75,
0xA3, 0x99, 0xE4, 0xA1, 0x9B, 0x5A, 0xF1, 0x29, 0xA0, 0x64, 0x9E, 0x18, 0x41, 0x80, 0x2C, 0x79,
0x20, 0x8B, 0xAB, 0x90, 0x08, 0xB8, 0xA9, 0x77, 0x12, 0xF9, 0x0E, 0x88, 0xE9, 0x04, 0xFB, 0x86,
0x0F, 0xE0, 0xA8, 0x5C, 0xE6, 0x21, 0xCD, 0x3B, 0x00, 0x78, 0xFC, 0xF6, 0xE3, 0x37, 0xB2, 0x91
};
unsigned char table2[256] = {
0xF3, 0xE4, 0x1B, 0x38, 0xE5, 0x6F, 0xE8, 0x9D, 0x3E, 0x55, 0xBA, 0xC7, 0xAC, 0xEA, 0x66, 0xA2,
0xB9, 0x7A, 0x34, 0x43, 0x02, 0x4E, 0xFE, 0x36, 0x41, 0x57, 0x1A, 0xB1, 0x31, 0x87, 0x04, 0x52,
0x21, 0x22, 0xE1, 0x13, 0x7F, 0x03, 0x3A, 0x90, 0xF7, 0x69, 0x78, 0x12, 0x83, 0x0B, 0x9A, 0x97,
0x4D, 0xB7, 0x8C, 0xBF, 0x2D, 0x94, 0xD1, 0x93, 0x2F, 0x42, 0x23, 0xA4, 0xE0, 0x92, 0xDC, 0x68,
0xD3, 0xDD, 0xAF, 0x91, 0x9F, 0xED, 0x3D, 0x8F, 0xA1, 0x51, 0xD9, 0xE9, 0x70, 0x28, 0xEF, 0xB3,
0x49, 0xA5, 0x0D, 0xC5, 0xD0, 0x60, 0xB4, 0x2B, 0x07, 0xF8, 0xDF, 0xE6, 0x16, 0xC0, 0x30, 0x71,
0x85, 0xFD, 0x72, 0x95, 0x29, 0x79, 0x0A, 0x7B, 0x46, 0x11, 0x7D, 0x88, 0x1D, 0x2A, 0x48, 0x1F,
0x45, 0x89, 0x47, 0xEE, 0xBB, 0xBE, 0x6E, 0xC3, 0x6C, 0xCE, 0x10, 0x5A, 0x2C, 0xCA, 0xFB, 0xB2,
0xCB, 0x1C, 0x9C, 0xEC, 0x2E, 0x56, 0x59, 0x9B, 0xA6, 0x53, 0xAE, 0x17, 0x25, 0xC1, 0x3F, 0x6A,
0x0F, 0x09, 0x01, 0xA3, 0xD6, 0xA0, 0xD8, 0x08, 0xE3, 0x74, 0x06, 0x6D, 0x19, 0x98, 0x1E, 0x77,
0x76, 0xBC, 0xEB, 0x3C, 0xB0, 0xC4, 0xC8, 0x64, 0x0E, 0x86, 0x63, 0xD7, 0xDB, 0xBD, 0xA7, 0x82,
0x39, 0x4F, 0x27, 0xD2, 0x5F, 0x73, 0xF4, 0x75, 0x6B, 0xC2, 0xD5, 0x67, 0x5D, 0x80, 0xAB, 0x81,
0xDE, 0xF0, 0xAD, 0xAA, 0xCD, 0xB6, 0xF6, 0x7C, 0xFC, 0x33, 0x05, 0x14, 0x96, 0x15, 0xC9, 0x9E,
0x35, 0x5C, 0x7E, 0x44, 0x54, 0x58, 0x3B, 0x40, 0x20, 0xA8, 0x8B, 0x5E, 0x4A, 0x24, 0x99, 0x8E,
0xF5, 0xB5, 0x62, 0x00, 0x37, 0x5B, 0x18, 0x65, 0x8D, 0x32, 0xE2, 0xF9, 0xDA, 0x8A, 0xD4, 0xCC,
0x26, 0xF2, 0xF1, 0xE7, 0x4B, 0xC6, 0xCF, 0xFF, 0x4C, 0x84, 0x61, 0xFA, 0xB8, 0x0C, 0xA9, 0x50
};
unsigned char fixed[18] = {
0x67, 0x23, 0xFE, 0x30, 0x45, 0x33, 0xF8, 0x90, 0x99, 0x21, 0x07, 0xC1, 0xD0, 0x12, 0xB2, 0xA1, 0x07, 0x81
};
int GCD(int a, int b){
while( 1 )
{
a = a % b;
if( a == 0 )
return b;
b = b % a;
if( b == 0 )
return a;
}
}
int LCM(int a, int b)
{
if(a==0 || b==0)
return 1;
return (a*b)/GCD(a,b);
}
//pFWID -> 8 bytes
//pKey -> 64 byte buffer
void GenerateKey(unsigned char *pFWID, unsigned char *pKey){
memset(pKey,0, 64);
int i;
unsigned char y[16] = {0};
//take LCM of each two bytes in the FWID in turn
for(i=0;i<4;i++){
int a=pFWID[i*2];
int b=pFWID[i*2+1];
int lcm = LCM(a,b);
unsigned char hi = (lcm & 0xFF00) >> 8;
unsigned char lo = lcm & 0xFF;
y[i*4] = ((table1[hi] * 0xB5) - 3);
y[i*4 + 1] = ((table2[hi] * 0xB7) + 0x49);
y[i*4 + 2] = ((table1[lo] * 0xB5) - 3);
y[i*4 + 3] = ((table2[lo] * 0xB7) + 0x49);
}
//convert y
for(i=0;i<16;i++){
y[i] = invTable[y[i]];
}
//hash
SHA1_CTX context;
SHA1Init(&context);
SHA1Update(&context, fixed, 18);
SHA1Update(&context, y, 16);
SHA1Final(pKey, &context);
}
//pDataBase -> iTunesDB
//pFWID -> 8 bytes
//pHash -> 20 byte buffer
void GenerateHash(unsigned char *pFWID, unsigned char *pDataBase0, long lSize, unsigned char *pHash)
{
unsigned char *pDataBase = (unsigned char*)malloc(lSize);
memcpy(pDataBase,pDataBase0,lSize);
//generate invtable
unsigned char key[64] = {0};
GenerateKey(pFWID, key);
//hmac sha1
int i;
for (i=0; i < 64; i++)
key[i] ^= 0x36;
SHA1_CTX context;
SHA1Init(&context);
SHA1Update(&context, key, 64);
SHA1Update(&context, pDataBase, lSize);
SHA1Final(pHash, &context);
for (i=0; i < 64; i++)
key[i] ^= 0x36 ^ 0x5c;
SHA1Init(&context);
SHA1Update(&context, key, 64);
SHA1Update(&context, pHash, 20);
SHA1Final(pHash, &context);
free(pDataBase);
}
+1
View File
@@ -0,0 +1 @@
void GenerateHash(unsigned char *pFWID, unsigned char *pDataBase, long lSize, unsigned char *pHash);
@@ -0,0 +1,914 @@
/*
*
*
* Copyright (c) 2007 Will Fisher (will.fisher@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*
*/
#include "iPodArtworkDB.h"
#include <algorithm>
#include <strsafe.h>
//utilities
#define SAFEDELETE(x) {if(x) delete (x); (x)=0;}
#define SAFEFREE(x) {if(x) free(x); (x)=0;}
static __forceinline unsigned short rev1(const BYTE *data)
{
return ((unsigned short) data[0]);
}
static __forceinline unsigned short rev1i(const BYTE *data, int &ptr)
{
unsigned short ret = rev1(data+ptr);
ptr+=1;
return ret;
}
static __forceinline unsigned short rev2(const BYTE *data)
{
unsigned short ret;
ret = ((unsigned short) data[1]) << 8;
ret += ((unsigned short) data[0]);
return ret;
}
static __forceinline unsigned short rev2i(const BYTE *data, int &ptr)
{
unsigned short ret = rev2(data+ptr);
ptr+=2;
return ret;
}
// get 4 bytes from data, reversed
static __forceinline unsigned int rev4(const BYTE * data)
{
unsigned int ret;
ret = ((unsigned long) data[3]) << 24;
ret += ((unsigned long) data[2]) << 16;
ret += ((unsigned long) data[1]) << 8;
ret += ((unsigned long) data[0]);
return ret;
}
static __forceinline unsigned int rev4i(const BYTE * data, int &ptr)
{
unsigned int ret = rev4(data+ptr);
ptr+=4;
return ret;
}
// get 4 bytes from data
static __forceinline unsigned long get4(const unsigned char * data)
{
unsigned long ret;
ret = ((unsigned long) data[0]) << 24;
ret += ((unsigned long) data[1]) << 16;
ret += ((unsigned long) data[2]) << 8;
ret += ((unsigned long) data[3]);
return ret;
}
static __forceinline unsigned long get4i(const unsigned char * data, int &ptr)
{
unsigned long ret = get4(data+ptr);
ptr+=4;
return ret;
}
// get 8 bytes from data
static __forceinline unsigned __int64 get8(const unsigned char * data)
{
unsigned __int64 ret;
ret = get4(data);
ret = ret << 32;
ret+= get4(data+4);
return ret;
}
// get 8 bytes from data
static __forceinline unsigned __int64 get8i(const unsigned char * data, int &ptr)
{
unsigned __int64 ret = get8(data+ptr);
ptr+=8;
return ret;
}
// reverse 8 bytes in place
static __forceinline unsigned __int64 rev8(unsigned __int64 number)
{
unsigned __int64 ret;
ret = (number&0x00000000000000FF) << 56;
ret+= (number&0x000000000000FF00) << 40;
ret+= (number&0x0000000000FF0000) << 24;
ret+= (number&0x00000000FF000000) << 8;
ret+= (number&0x000000FF00000000) >> 8;
ret+= (number&0x0000FF0000000000) >> 24;
ret+= (number&0x00FF000000000000) >> 40;
ret+= (number&0xFF00000000000000) >> 56;
return ret;
}
static __forceinline void putmh(const char* x, BYTE *data, int &ptr) {
data[0+ptr]=x[0];
data[1+ptr]=x[1];
data[2+ptr]=x[2];
data[3+ptr]=x[3];
ptr+=4;
}
//write 4 bytes reversed
static __forceinline void rev4(const unsigned long number, unsigned char * data)
{
data[3] = (unsigned char)(number >> 24) & 0xff;
data[2] = (unsigned char)(number >> 16) & 0xff;
data[1] = (unsigned char)(number >> 8) & 0xff;
data[0] = (unsigned char)number & 0xff;
}
static __forceinline void rev4i(const unsigned int number, BYTE* data, int &ptr)
{
rev4(number,data+ptr);
ptr+=4;
}
static __forceinline void rev2(const unsigned short number, unsigned char * data)
{
data[1] = (unsigned char)(number >> 8) & 0xff;
data[0] = (unsigned char)number & 0xff;
}
static __forceinline void rev2i(const unsigned short number, BYTE* data, int &ptr)
{
rev2(number,data+ptr);
ptr+=2;
}
static __forceinline void rev1(const unsigned char number, unsigned char * data)
{
data[0] = number;
}
static __forceinline void rev1i(const unsigned char number, BYTE* data, int &ptr)
{
rev1(number,data+ptr);
ptr+=1;
}
// write 8 bytes normal
static __forceinline void put8(unsigned __int64 number, unsigned char * data)
{
data[0] = (unsigned char)(number >> 56) & 0xff;
data[1] = (unsigned char)(number >> 48) & 0xff;
data[2] = (unsigned char)(number >> 40) & 0xff;
data[3] = (unsigned char)(number >> 32) & 0xff;
data[4] = (unsigned char)(number >> 24) & 0xff;
data[5] = (unsigned char)(number >> 16) & 0xff;
data[6] = (unsigned char)(number >> 8) & 0xff;
data[7] = (unsigned char)number & 0xff;
}
static __forceinline void put8i(unsigned __int64 number, unsigned char * data, int &ptr) {
put8(number,data+ptr);
ptr+=8;
}
static __forceinline void pad(BYTE * data, int endpoint, int& startpoint) {
if(endpoint == startpoint) return;
ZeroMemory(data+startpoint, endpoint - startpoint);
startpoint = endpoint;
}
///////////////////////////////////////////////////////////////////////////////
// ArtDB
ArtDB::ArtDB() :
headerlen(0x84),
totallen(0),
unk1(0),
unk2(2),
unk3(0),
nextid(0x40),
unk5(0),
unk6(0),
unk7(0),
unk8(0),
unk9(0),
unk10(0),
unk11(0),
imageListDS(0),
albumListDS(0),
fileListDS(0)
{
}
ArtDB::~ArtDB() {
SAFEDELETE(imageListDS);
SAFEDELETE(albumListDS);
SAFEDELETE(fileListDS);
}
int ArtDB::parse(BYTE * data, int len, wchar_t drive) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhfd",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x84) return -1;
totallen = rev4i(data,ptr);
unk1 = rev4i(data,ptr);
unk2 = rev4i(data,ptr);
int numchildren = rev4i(data,ptr);
unk3 = rev4i(data,ptr);
nextid = rev4i(data,ptr);
unk5 = rev8(get8i(data,ptr));
unk6 = rev8(get8i(data,ptr));
unk7 = rev4i(data,ptr);
unk8 = rev4i(data,ptr);
unk9 = rev4i(data,ptr);
unk10 = rev4i(data,ptr);
unk11 = rev4i(data,ptr);
ptr=headerlen;
for(int i=0; i<numchildren; i++) {
ArtDataSet * d = new ArtDataSet;
int p = d->parse(data+ptr,len-ptr);
if(p == -1) return -1;
switch(d->index) {
case 1: imageListDS = d; break;
case 2: albumListDS = d; break;
case 3: fileListDS = d; break;
default: delete d;
}
ptr+=p;
}
if(!imageListDS) imageListDS = new ArtDataSet(1);
if(!albumListDS) albumListDS = new ArtDataSet(2);
if(!fileListDS) fileListDS = new ArtDataSet(3);
for(ArtImageList::ArtImageMapIterator i = imageListDS->imageList->images.begin(); i!=imageListDS->imageList->images.end(); i++) {
if(i->second) {
for(auto j = i->second->dataobjs.begin(); j != i->second->dataobjs.end(); j++) {
if((*j)->image) {
ArtFile *f = fileListDS->fileList->getFile((*j)->image->corrid);
if(!f) {
f = new ArtFile();
f->corrid = (*j)->image->corrid;
fileListDS->fileList->files.push_back(f);
}
f->images.push_back(new ArtFileImage((*j)->image->ithmboffset,(*j)->image->imagesize,1));
}
}
}
}
for(auto i = fileListDS->fileList->files.begin(); i!=fileListDS->fileList->files.end(); i++) {
wchar_t file[MAX_PATH] = {0};
StringCchPrintfW(file, MAX_PATH, L"%c:\\iPod_Control\\Artwork\\F%04d_1.ithmb",drive,(*i)->corrid);
(*i)->file = _wcsdup(file);
(*i)->sortImages();
}
return totallen;
}
int ArtDB::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhfd",data,ptr);
rev4i(headerlen,data,ptr);
rev4i(0,data,ptr); // fill total len here later
rev4i(unk1,data,ptr);
rev4i(unk2,data,ptr); // always seems to be "2" when iTunes writes it
rev4i(3,data,ptr); // num children
rev4i(unk3,data,ptr);
rev4i(nextid,data,ptr);
put8i(rev8(unk5),data,ptr);
put8i(rev8(unk6),data,ptr);
rev4i(unk7,data,ptr);
rev4i(unk8,data,ptr);
rev4i(unk9,data,ptr);
rev4i(unk10,data,ptr);
rev4i(unk11,data,ptr);
pad(data,headerlen,ptr);
// write out children
int p;
p = imageListDS->write(data+ptr,len-ptr);
if(p<0) return -1;
ptr+=p;
p = albumListDS->write(data+ptr,len-ptr);
if(p<0) return -1;
ptr+=p;
p = fileListDS->write(data+ptr,len-ptr);
if(p<0) return -1;
ptr+=p;
rev4(ptr,&data[8]); // fill in total length
return ptr;
}
void ArtDB::makeEmptyDB(wchar_t drive) {
imageListDS = new ArtDataSet(1);
albumListDS = new ArtDataSet(2);
fileListDS = new ArtDataSet(3);
for(auto i = fileListDS->fileList->files.begin(); i!=fileListDS->fileList->files.end(); i++) {
wchar_t file[MAX_PATH] = {0};
StringCchPrintfW(file, MAX_PATH, L"%c:\\iPod_Control\\Artwork\\F%04d_1.ithmb",drive,(*i)->corrid);
(*i)->file = _wcsdup(file);
}
}
///////////////////////////////////////////////////////////////////////////////
// ArtDatSet
ArtDataSet::ArtDataSet() :
headerlen(0x60),
totallen(0),
index(0),
imageList(0),
albumList(0),
fileList(0)
{
}
ArtDataSet::ArtDataSet(int idx) :
headerlen(0x60),
totallen(0),
index(idx),
imageList(0),
albumList(0),
fileList(0)
{
switch(idx) {
case 1: imageList = new ArtImageList; break;
case 2: albumList = new ArtAlbumList; break;
case 3: fileList = new ArtFileList; break;
default: index=0;
}
}
ArtDataSet::~ArtDataSet() {
SAFEDELETE(imageList);
SAFEDELETE(albumList);
SAFEDELETE(fileList);
}
int ArtDataSet::parse(BYTE *data, int len) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhsd",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x60) return -1;
totallen = rev4i(data,ptr);
index = rev4i(data,ptr);
ptr=headerlen;
int p=0;
switch(index) {
case 1: imageList = new ArtImageList; p = imageList->parse(data+ptr, len-ptr); break;
case 2: albumList = new ArtAlbumList; p = albumList->parse(data+ptr, len-ptr); break;
case 3: fileList = new ArtFileList; p = fileList->parse(data+ptr, len-ptr); break;
}
if(p < 0) return -1;
return totallen;
}
int ArtDataSet::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhsd",data,ptr);
rev4i(headerlen,data,ptr);
rev4i(0,data,ptr); // fill total len here later
rev4i(index,data,ptr);
pad(data,headerlen,ptr);
int p=0;
switch(index) {
case 1: p=imageList->write(data+ptr, len-ptr); break;
case 2: p=albumList->write(data+ptr, len-ptr); break;
case 3: p=fileList->write(data+ptr, len-ptr); break;
}
if(p<0) return -1;
ptr+=p;
rev4(ptr,&data[8]); // fill in total length
return ptr;
}
///////////////////////////////////////////////////////////////////////////////
// ArtImageList
ArtImageList::ArtImageList() :
headerlen(0x5c)
{
}
ArtImageList::~ArtImageList() {
for(ArtImageMapIterator f = images.begin(); f != images.end(); f++)
delete f->second;
images.clear();
}
int ArtImageList::parse(BYTE *data, int len) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhli",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x5c) return -1;
int children = rev4i(data,ptr);
ptr=headerlen;
for(int i=0; i<children; i++) {
ArtImage * f = new ArtImage;
int p = f->parse(data+ptr,len-ptr);
if(p<0) {delete f; return -1;}
ptr+=p;
images.insert(ArtImageMapPair(f->songid,f));
}
return ptr;
}
int ArtImageList::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhli",data,ptr);
rev4i(headerlen,data,ptr);
rev4i(images.size(),data,ptr);
pad(data,headerlen,ptr);
for(ArtImageMapIterator f = images.begin(); f != images.end(); f++) {
int p = f->second->write(data+ptr,len-ptr);
if(p<0) return -1;
ptr+=p;
}
return ptr;
}
///////////////////////////////////////////////////////////////////////////////
// ArtImage
ArtImage::ArtImage() :
headerlen(0x98),
totallen(0),
id(0),
songid(0),
unk4(0),
rating(0),
unk6(0),
originalDate(0),
digitizedDate(0),
srcImageSize(0)
{
}
ArtImage::~ArtImage()
{
for (auto obj : dataobjs)
{
delete obj;
}
dataobjs.clear();
}
int ArtImage::parse(BYTE *data, int len) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhii",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x98) return -1;
totallen = rev4i(data,ptr);
int numchildren = rev4i(data,ptr);
id = rev4i(data,ptr);
songid = rev8(get8i(data,ptr));
unk4 = rev4i(data,ptr);
rating = rev4i(data,ptr);
unk6 = rev4i(data,ptr);
originalDate = rev4i(data,ptr);
digitizedDate = rev4i(data,ptr);
srcImageSize = rev4i(data,ptr);
ptr = headerlen;
for(int i=0; i<numchildren; i++) {
ArtDataObject *d = new ArtDataObject;
int p = d->parse(data+ptr,len-ptr);
if(p<0) { delete d; return -1; }
ptr+=p;
// fuck with d. ugh.
if((d->type == 2 || d->type == 5) && d->data) { // this is a container mhod
d->image = new ArtImageName;
int p2 = d->image->parse(d->data,d->datalen);
if(p2>0) {
SAFEFREE(d->data);
d->datalen=0;
} else SAFEDELETE(d->image);
}
dataobjs.push_back(d);
}
return totallen;
}
template<class T>
BYTE *expandMemWrite(T * x, int &len, int maxsize=1024000) {
int s = 1024;
for(;;) {
BYTE *r = (BYTE*)malloc(s);
int p = x->write(r,s);
if(p>0) {
len=p;
return r;
}
free(r);
s = s+s;
if(s > maxsize) break;
}
return NULL;
}
int ArtImage::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhii",data,ptr);
rev4i(headerlen,data,ptr);
rev4i(0,data,ptr); // fill in total length later
rev4i(dataobjs.size(),data,ptr);
rev4i(id,data,ptr);
put8i(rev8(songid),data,ptr);
rev4i(unk4,data,ptr);
rev4i(rating,data,ptr);
rev4i(unk6,data,ptr);
rev4i(originalDate,data,ptr);
rev4i(digitizedDate,data,ptr);
rev4i(srcImageSize,data,ptr);
pad(data,headerlen,ptr);
for(auto f = dataobjs.begin(); f != dataobjs.end(); f++) {
if((*f)->image) {
int len=0;
BYTE *b = expandMemWrite((*f)->image,len);
if(!b) return -1;
(*f)->data = b;
(*f)->datalen = len;
}
int p = (*f)->write(data+ptr,len-ptr);
if((*f)->image) {
SAFEFREE((*f)->data);
(*f)->datalen=0;
}
if(p<0) return -1;
ptr+=p;
}
rev4(ptr,&data[8]); // fill in total length
return ptr;
}
///////////////////////////////////////////////////////////////////////////////
// ArtDataObj
ArtDataObject::ArtDataObject() :
headerlen(0x18),
type(0),
data(0),
datalen(0),
image(0),
unk1(0)
{
}
ArtDataObject::~ArtDataObject() {
SAFEDELETE(image);
SAFEFREE(data);
}
int ArtDataObject::parse(BYTE *data, int len) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhod",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x18) return -1;
int totallen = rev4i(data,ptr);
if(len < totallen) return -1;
type = rev2i(data,ptr);
unk1 = (unsigned char)rev1i(data,ptr);
short padding = rev1i(data,ptr);
ptr = headerlen;
if(type == 3 && rev2(&data[totallen-2]) == 0)
datalen = wcslen((wchar_t*)(data+ptr+12))*sizeof(wchar_t) + 12;
else
datalen = totallen - headerlen - padding;
if(datalen > 0x400 || datalen < 0) return -1;
this->data = (BYTE*)malloc(datalen);
memcpy(this->data,data+ptr,datalen);
return totallen;
}
int ArtDataObject::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhod",data,ptr);
rev4i(headerlen,data,ptr);
short padding = (4 - ((headerlen + datalen) % 4));// % 4;
if(padding == 4) padding = 0;
rev4i(headerlen+datalen+padding,data,ptr);
rev2i(type,data,ptr);
rev1i(unk1,data,ptr);
rev1i((unsigned char)padding,data,ptr);
pad(data,headerlen,ptr);
//write data
memcpy(data+ptr,this->data,datalen);
ptr+=datalen;
//add padding...
pad(data,ptr+padding,ptr);
return ptr;
}
void ArtDataObject::GetString(wchar_t * str, int len) {
if(rev4(data+4) != 2) { str[0]=0; return; }//not utf-16!
int l = (rev4(data)/sizeof(wchar_t));
StringCchCopyN(str, len, (wchar_t*)&data[12], l);
//lstrcpyn(str,(wchar_t*)&data[12],min(l,len));
}
void ArtDataObject::SetString(wchar_t * str) {
SAFEFREE(data);
datalen = wcslen(str)*sizeof(wchar_t) + 12;
data = (BYTE*)malloc(datalen);
rev4(wcslen(str)*sizeof(wchar_t),data);
rev4(2,data+4); //type 2 means utf-16
rev4(0,data+8); //unk
memcpy(data+12,str,wcslen(str)*sizeof(wchar_t));
}
///////////////////////////////////////////////////////////////////////////////
// ArtImageName
ArtImageName::ArtImageName() :
headerlen(0x4c),
totallen(0),
corrid(0),
ithmboffset(0),
imagesize(0),
vpad(0),
hpad(0),
imgh(0),
imgw(0),
filename(0)
{
}
ArtImageName::~ArtImageName() {
SAFEDELETE(filename);
}
int ArtImageName::parse(BYTE *data, int len) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhni",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x4c) return -1;
totallen = rev4i(data,ptr);
int children = rev4i(data,ptr);
corrid = rev4i(data,ptr);
ithmboffset = rev4i(data,ptr);
imagesize = rev4i(data,ptr);
vpad = (short)rev2i(data,ptr);
hpad = (short)rev2i(data,ptr);
imgw = rev2i(data,ptr);
imgh = rev2i(data,ptr);
ptr = headerlen;
if(children) {
filename = new ArtDataObject();
int p = filename->parse(data+ptr,len-ptr);
if(p<0) SAFEDELETE(filename);
}
return totallen;
}
int ArtImageName::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhni",data,ptr);
rev4i(headerlen,data,ptr);
rev4i(0,data,ptr); // fill in totallen later
rev4i(filename?1:0,data,ptr); //num children
rev4i(corrid,data,ptr);
rev4i(ithmboffset,data,ptr);
rev4i(imagesize,data,ptr);
rev2i(vpad,data,ptr);
rev2i(hpad,data,ptr);
rev2i(imgw,data,ptr);
rev2i(imgh,data,ptr);
pad(data,headerlen,ptr);
if(filename) {
int p = filename->write(data+ptr,len-ptr);
if(p<0) return -1;
ptr+=p;
}
rev4(ptr,&data[8]); // fill in totallen
return ptr;
}
///////////////////////////////////////////////////////////////////////////////
// ArtAlbumList
ArtAlbumList::ArtAlbumList() :
headerlen(0x5c)
{
}
ArtAlbumList::~ArtAlbumList() {}
int ArtAlbumList::parse(BYTE *data, int len) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhla",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x5c) return -1;
int children = rev4i(data,ptr);
if(children != 0) return -1;
return headerlen;
}
int ArtAlbumList::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhla",data,ptr);
rev4i(headerlen,data,ptr);
rev4i(0,data,ptr); // num children
pad(data,headerlen,ptr);
return ptr;
}
///////////////////////////////////////////////////////////////////////////////
// ArtFileList
ArtFileList::ArtFileList() :
headerlen(0x5c)
{
}
ArtFileList::~ArtFileList()
{
for (auto file : files)
{
delete file;
}
files.clear();
}
int ArtFileList::parse(BYTE *data, int len) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhlf",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x5c) return -1;
int children = rev4i(data,ptr);
ptr = headerlen;
for(int i=0; i<children; i++) {
ArtFile * f = new ArtFile;
int p = f->parse(data+ptr,len-ptr);
if(p<0) { delete f; return -1; }
ptr+=p;
files.push_back(f);
}
return ptr;
}
int ArtFileList::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhlf",data,ptr);
rev4i(headerlen,data,ptr);
rev4i(files.size(),data,ptr); // num children
pad(data,headerlen,ptr);
for(auto f = files.begin(); f != files.end(); f++) {
int p = (*f)->write(data+ptr,len-ptr);
if(p<0) return -1;
ptr+=p;
}
return ptr;
}
ArtFile * ArtFileList::getFile(int corrid) {
for(auto i = files.begin(); i!=files.end(); i++) {
if((*i)->corrid == corrid) return *i;
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
// ArtFile
ArtFile::ArtFile() :
headerlen(0x7c),
corrid(0),
imagesize(0),
file(0)
{
}
ArtFile::~ArtFile() {
SAFEFREE(file);
}
int ArtFile::parse(BYTE *data, int len) {
int ptr=4;
if(len < headerlen) return -1;
if (_strnicmp((char *)data,"mhif",4)) return -1;
headerlen = rev4i(data,ptr);
if(headerlen < 0x7c) return -1;
int totallen = rev4i(data,ptr);
rev4i(data,ptr); // might not be numchildren, it's really unk1
corrid = rev4i(data,ptr);
imagesize = rev4i(data,ptr);
return totallen;
}
int ArtFile::write(BYTE *data, int len) {
int ptr=0;
if(headerlen > len) return -1;
putmh("mhif",data,ptr);
rev4i(headerlen,data,ptr);
rev4i(0,data,ptr); // total len, fill in later
rev4i(0,data,ptr); // numchildren/unk1
rev4i(corrid,data,ptr);
rev4i(imagesize,data,ptr);
pad(data,headerlen,ptr);
// write children, if we had any...
rev4(ptr,&data[8]); // fill in total len
return ptr;
}
struct ArtFileImageSort {
bool operator()(ArtFileImage*& ap,ArtFileImage*& bp) {
return ap->start < bp->start;
}
};
void ArtFile::sortImages() {
std::sort(images.begin(),images.end(),ArtFileImageSort());
for(size_t i = 1; i != images.size(); i++)
{
if(images[i]->start == images[i-1]->start)
{
images.erase(images.begin() + i);
i--;
images[i]->refcount++;
}
}
}
size_t ArtFile::getNextHole(size_t size) {
size_t s=0;
for(auto i = images.begin(); i!=images.end(); i++) {
if((*i)->start - s >= size) return s;
s = (*i)->start + (*i)->len;
}
return s;
}
bool writeDataToThumb(wchar_t *file, unsigned short * data, int len) {
FILE * f = _wfopen(file,L"ab");
if(!f) return false;
fwrite(data,len,sizeof(short),f);
fclose(f);
return true;
}
@@ -0,0 +1,232 @@
/*
*
*
* Copyright (c) 2007 Will Fisher (will.fisher@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*
*
*/
#ifndef __IPODARTDB_H__
#define __IPODARTDB_H__
#pragma once
//#include <stdio.h>
#include <windows.h>
#include <vector>
#include <map>
#include <bfc/platform/types.h>
class ArtDB;
class ArtDataSet;
class ArtImageList;
class ArtImage;
class ArtImageName;
class ArtDataObject;
class ArtAlbumList;
class ArtFileList;
class ArtFile;
class ArtFileImage;
// this contains our whole art database
class ArtDB { //mhfd
public:
int headerlen; //0x84
int totallen;
int unk1;
int unk2; // must be 2
// numchildren // should be 3
int unk3;
uint32_t nextid; // for ArtImage ids, starts at 0x40
__int64 unk5;
__int64 unk6;
int unk7; // 2
int unk8; // 0
int unk9; // 0
int unk10;
int unk11;
ArtDataSet * imageListDS;
ArtDataSet * albumListDS;
ArtDataSet * fileListDS;
ArtDB();
~ArtDB();
int parse(BYTE * data, int len, wchar_t drive);
int write(BYTE * data, int len);
void makeEmptyDB(wchar_t drive);
};
class ArtDataSet { //mhsd
public:
int headerlen; //0x60
int totallen;
int index; // 1=image list, 2=album list, 3=file list
ArtImageList * imageList;
ArtAlbumList * albumList;
ArtFileList * fileList;
ArtDataSet();
ArtDataSet(int idx);
~ArtDataSet();
int parse(BYTE *data, int len);
int write(BYTE *data, int len);
};
// contains a list of images
class ArtImageList { //mhli
public:
typedef std::map<uint64_t ,ArtImage*> ArtImageMap;
typedef ArtImageMap::iterator ArtImageMapIterator;
typedef ArtImageMap::value_type ArtImageMapPair;
int headerlen; //0x5c
//int numchildren;
ArtImageMap images;
ArtImageList();
~ArtImageList();
int parse(BYTE *data, int len);
int write(BYTE *data, int len);
};
// contains a reference to an image within an .ithmb file
class ArtImage { //mhii
public:
int headerlen; //0x98
int totallen;
//int numchildren;
uint32_t id;
uint64_t songid;
int32_t unk4;
int32_t rating;
int32_t unk6;
uint32_t originalDate; //0
uint32_t digitizedDate; //0
uint32_t srcImageSize; // in bytes
std::vector<ArtDataObject*> dataobjs;
ArtImage();
~ArtImage();
int parse(BYTE *data, int len);
int write(BYTE *data, int len);
};
class ArtDataObject { //mhod
public:
int headerlen; //0x18
// total length
short type;
unsigned char unk1;
// unsigned char padding; // must pad to a multiple of 4 bytes! this is usually 2, but can be 0,1,2 or 3
BYTE * data;
int datalen;
ArtImageName * image;
ArtDataObject();
~ArtDataObject();
int parse(BYTE *data, int len);
int write(BYTE *data, int len);
void GetString(wchar_t * str, int len);
void SetString(wchar_t * str);
};
class ArtImageName { //mhni
public:
int headerlen; //0x4c
int totallen;
//num children = 1
unsigned int corrid;
unsigned int ithmboffset;
unsigned int imagesize; // in bytes
short vpad;
short hpad;
unsigned short imgh;
unsigned short imgw;
ArtDataObject* filename;
ArtImageName();
~ArtImageName();
int parse(BYTE *data, int len);
int write(BYTE *data, int len);
};
// this is only used in photo databases (which we don't care about) so it's only a stub
class ArtAlbumList { //mhla
public:
int headerlen; //0x5c
//num children, should be 0 for artwork db
ArtAlbumList();
~ArtAlbumList();
int parse(BYTE *data, int len);
int write(BYTE *data, int len);
};
// this contains the list of .ithmb files
class ArtFileList { //mhlf
public:
int headerlen; //0x5c
// num children
std::vector<ArtFile*> files;
ArtFileList();
~ArtFileList();
int parse(BYTE *data, int len);
int write(BYTE *data, int len);
ArtFile * getFile(int corrid);
};
// this talks about a .ithmb file
class ArtFile { //mhif
public:
int headerlen; //0x7c
unsigned int corrid;
unsigned int imagesize; // bytes
ArtFile();
~ArtFile();
int parse(BYTE *data, int len);
int write(BYTE *data, int len);
std::vector<ArtFileImage*> images;
wchar_t * file;
void sortImages();
size_t getNextHole(size_t size);
};
class ArtFileImage {
public:
size_t start;
size_t len;
int refcount;
ArtFileImage(size_t start, size_t len, int refcount) : start(start), len(len), refcount(refcount) {}
};
bool writeDataToThumb(wchar_t *file, unsigned short * data, int len);
#endif //__IPODARTDB_H__
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+142
View File
@@ -0,0 +1,142 @@
#ifndef _IPODDEVICE_H_
#define _IPODDEVICE_H_
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <shlobj.h>
#include <time.h>
#include "..\..\General\gen_ml/ml.h"
#include "..\..\Library\ml_pmp/pmp.h"
#include "..\..\Library\ml_pmp/transcoder.h"
#include "../winamp/wa_ipc.h"
#include "../winamp/ipc_pe.h"
#include "iPodDB.h"
#include "resource.h"
#include "..\..\General\gen_ml/itemlist.h"
#include "yail.h"
#include "iPodArtworkDB.h"
#include "iPodInfo.h"
#include <vector>
class iPodDevice : public Device {
public:
HWND gapscanner;
C_ItemList playlists; // list of iPod_mhyp*
Transcoder * transcoder;
iPod_mhbd * db;
char drive;
wchar_t driveW;
int dirnum;
__int64 transferQueueLength;
int image16;
int image160;
ArtDB * artdb;
std::vector<const ArtworkFormat*> thumbs;
uint8_t *fwid;
const iPodInfo *info;
iPodDevice(char drive);
virtual ~iPodDevice();
virtual int parseiTunesDB(bool parseArt);
virtual int writeiTunesDB();
virtual void getFilename(char * buf, int len, songid_t song);
virtual void getFilename(wchar_t *buf, int len, songid_t song);
virtual __int64 getDeviceCapacityAvailable(); // in bytes
virtual __int64 getDeviceCapacityTotal(); // in bytes
virtual void Eject(); // if you ejected successfully, you MUST call plugin.deviceDisconnected(this) and delete this;
virtual void Close(); // save any changes, and call plugin.deviceDisconnected(this) AND delete this;
// return 0 for success, -1 for failed or cancelled
virtual int transferTrackToDevice(const itemRecordW * track, // the track to transfer
void * callbackContext, //pass this to the callback
void (*callback)(void * callbackContext, wchar_t * status), // call this with stats every so often so the GUI can be updated
songid_t * songid, // fill in the songid when you are finished
int * killswitch); // if this gets set to 1, the transfer has been cancelled by the user
virtual int trackAddedToTransferQueue(const itemRecordW *track); // return 0 to accept, -1 for "not enough space", -2 for "incorrect format"
virtual void trackRemovedFromTransferQueue(const itemRecordW *track);
virtual __int64 getTrackSizeOnDevice(const itemRecordW *track); // return the amount of space taken up on the device by the track, or 0 for incompatable (usually the filesize, unless you are transcoding)
virtual void deleteTrack(songid_t songid); // physically remove from device. Be sure to remove it from all the playlists!
virtual void commitChanges(){writeiTunesDB();} // optional. Will be called at a good time to save changes
virtual int getPlaylistCount(); // always at least 1. playlistnumber 0 is the Master Playlist containing all tracks.
// PlaylistName(0) should return the name of the device.
virtual void getPlaylistName(int playlistnumber, wchar_t *buf, int len);
virtual int getPlaylistLength(int playlistnumber);
virtual songid_t getPlaylistTrack(int playlistnumber,int songnum); // returns a songid
virtual void setPlaylistName(int playlistnumber, const wchar_t *buf); // with playlistnumber==0, set the name of the device.
virtual void playlistSwapItems(int playlistnumber, int posA, int posB); // swap the songs at position posA and posB
virtual void sortPlaylist(int playlistnumber, int sortBy);
virtual void addTrackToPlaylist(int playlistnumber, songid_t songid); // adds songid to the end of the playlist
virtual void removeTrackFromPlaylist(int playlistnumber, int songnum); //where songnum is the position of the track in the playlist
virtual void deletePlaylist(int playlistnumber);
virtual int newPlaylist(const wchar_t *name); // create empty playlist, returns playlistnumber
virtual void getTrackArtist(songid_t songid, wchar_t *buf, int len);
virtual void getTrackAlbum(songid_t songid, wchar_t *buf, int len);
virtual void getTrackTitle(songid_t songid, wchar_t *buf, int len);
virtual int getTrackTrackNum(songid_t songid);
virtual int getTrackDiscNum(songid_t songid);
virtual void getTrackGenre(songid_t songid, wchar_t *buf, int len);
virtual int getTrackYear(songid_t songid);
virtual __int64 getTrackSize(songid_t songid); // in bytes
virtual int getTrackLength(songid_t songid); // in millisecs
virtual int getTrackBitrate(songid_t songid); // in kbps
virtual int getTrackPlayCount(songid_t songid);
virtual int getTrackRating(songid_t songid); //0-5
virtual __time64_t getTrackLastPlayed(songid_t songid); // in unix time format
virtual __time64_t getTrackLastUpdated(songid_t songid); // in unix time format
virtual void getTrackAlbumArtist(songid_t songid, wchar_t * buf, int len);
virtual void getTrackComposer(songid_t songid, wchar_t * buf, int len);
virtual int getTrackType(songid_t songid);
virtual void getTrackExtraInfo(songid_t songid, const wchar_t *field, wchar_t * buf, int len); //optional
// feel free to ignore any you don't support
virtual void setTrackArtist(intptr_t songid, const wchar_t *value);
virtual void setTrackAlbum(intptr_t songid, const wchar_t *value);
virtual void setTrackTitle(intptr_t songid, const wchar_t *value);
virtual void setTrackTrackNum(intptr_t songid, int value);
virtual void setTrackDiscNum(intptr_t songid, int value);
virtual void setTrackGenre(intptr_t songid, const wchar_t *value);
virtual void setTrackYear(intptr_t songid, int year);
virtual void setTrackPlayCount(intptr_t songid, int value);
virtual void setTrackRating(intptr_t songid, int value);
virtual void setTrackLastPlayed(intptr_t songid, __time64_t value); // in unix time format
virtual void setTrackLastUpdated(intptr_t songid, __time64_t value); // in unix time format
virtual void setTrackAlbumArtist(songid_t songid, const wchar_t *value);
virtual void setTrackComposer(songid_t songid, const wchar_t *value);
virtual void setTrackExtraInfo(intptr_t songid, const wchar_t *field, const wchar_t *value) {}; //optional
virtual bool playTracks(songid_t * songidList, int listLength, int startPlaybackAt, bool enqueue); // return false if unsupported
virtual intptr_t extraActions(intptr_t param1, intptr_t param2, intptr_t param3,intptr_t param4); // This does nothing yet. For future use.
virtual bool copyToHardDriveSupported() {return true;}
virtual __int64 songSizeOnHardDrive(songid_t song) {return getTrackSize(song);} // how big a song will be when copied back. Return -1 for not supported.
virtual int copyToHardDrive(songid_t song, // the song to copy
wchar_t * path, // path to copy to, in the form "c:\directory\song". The directory will already be created, you must append ".mp3" or whatever to this string! (there is space for at least 10 new characters).
void * callbackContext, //pass this to the callback
void (*callback)(void * callbackContext, wchar_t * status), // call this every so often so the GUI can be updated. Including when finished!
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
); // -1 for failed/not supported. 0 for success.
// art functions
virtual void setArt(songid_t songid, void *buf, int w, int h); //buf is in format ARGB32*
virtual pmpart_t getArt(songid_t songid);
virtual void releaseArt(pmpart_t art);
virtual int drawArt(pmpart_t art, HDC dc, int x, int y, int w, int h);
virtual void getArtNaturalSize(pmpart_t art, int *w, int *h);
virtual void setArtNaturalSize(pmpart_t art, int w, int h);
virtual void getArtData(pmpart_t art, void* data); // data ARGB32* is at natural size
virtual bool artIsEqual(pmpart_t a, pmpart_t b);
};
#endif // _IPODDEVICE_H_
File diff suppressed because it is too large Load Diff
+97
View File
@@ -0,0 +1,97 @@
#ifndef _IPOD_INFO_H_
#define _IPOD_INFO_H_
#define RGB_565 0
#define RGB_555 1
#define RGB_555_REC 2
typedef enum {
THUMB_INVALID = -1,
THUMB_COVER_SMALL,
THUMB_COVER_MEDIUM1,
THUMB_COVER_MEDIUM2,
THUMB_COVER_MEDIUM3,
THUMB_COVER_MEDIUM4,
THUMB_COVER_LARGE,
THUMB_PHOTO_SMALL,
THUMB_PHOTO_LARGE,
THUMB_PHOTO_FULL_SCREEN,
THUMB_PHOTO_TV_SCREEN,
} ThumbType;
typedef enum {
IPOD_COLOR_WHITE,
IPOD_COLOR_BLACK,
IPOD_COLOR_SILVER,
IPOD_COLOR_BLUE,
IPOD_COLOR_PINK,
IPOD_COLOR_GREEN,
IPOD_COLOR_ORANGE,
IPOD_COLOR_GOLD,
IPOD_COLOR_RED,
IPOD_COLOR_U2,
} iPodColor;
typedef enum {
IPOD_MODEL_INVALID=0,
IPOD_MODEL_COLOR=1,
IPOD_MODEL_REGULAR=2,
IPOD_MODEL_MINI=3,
IPOD_MODEL_SHUFFLE=4,
IPOD_MODEL_VIDEO=5,
IPOD_MODEL_NANO=6,
IPOD_MODEL_CLASSIC=7,
IPOD_MODEL_FATNANO=8,
IPOD_MODEL_TOUCH=9,
} iPodModel;
typedef struct {
ThumbType type;
int width;
int height;
int correlation_id;
int format;
int row_align;
int image_align;
} ArtworkFormat;
struct iPodModelInfo
{
// model_number is abbreviated: if the first character is not numeric, it is ommited. e.g. "MA350 -> A350", "M9829 -> 9829"
const wchar_t *model_number;
iPodModel model;
iPodColor color;
int image16;
int image160;
};
class iPodInfo
{
public:
iPodInfo(const iPodModelInfo *model);
~iPodInfo();
void SetFWID(const uint8_t *new_fwid);
int family_id;
wchar_t *model_number;
iPodModel model;
iPodColor color;
int image16;
int image160;
// Store the supported artwork formats if we
// can dynamically read it from the extended sysinfo xml
ArtworkFormat* supportedArtworkFormats;
size_t numberOfSupportedFormats;
unsigned char *fwid;
unsigned int shadow_db_version;
};
struct _iPodSerialToModel {
const wchar_t *serial;
const wchar_t *model_number;
};
typedef struct _iPodSerialToModel iPodSerialToModel;
iPodInfo *GetiPodInfo(wchar_t drive);
const ArtworkFormat* GetArtworkFormats(const iPodInfo* info);
#endif //_IPOD_INFO_H_
+523
View File
@@ -0,0 +1,523 @@
#include "iPodSD.h"
#include <math.h>
#include <assert.h>
// get 3 bytes from data (used in iTunesSD1)
static __forceinline unsigned long get3(const uint8_t * data)
{
unsigned long ret = 0;
ret += ((unsigned long) data[0]) << 16;
ret += ((unsigned long) data[1]) << 8;
ret += ((unsigned long) data[2]);
return ret;
}
//write 3 bytes normal (used in iTunesSD1)
static __forceinline void put3(const unsigned long number, uint8_t * data)
{
data[0] = (uint8_t)(number >> 16) & 0xff;
data[1] = (uint8_t)(number >> 8) & 0xff;
data[2] = (uint8_t)number & 0xff;
}
// pass data and ptr, updates ptr automatically (by reference)
static __forceinline void write_uint64_t(uint8_t *data, size_t &offset, uint64_t value)
{
memcpy(&data[offset], &value, 8);
offset+=8;
}
// pass data and ptr, updates ptr automatically (by reference)
static __forceinline void write_uint32_t(uint8_t *data, size_t &offset, uint32_t value)
{
memcpy(&data[offset], &value, 4);
offset+=4;
}
// pass data and ptr, updates ptr automatically (by reference)
static __forceinline void write_uint16_t(uint8_t *data, size_t &offset, uint16_t value)
{
memcpy(&data[offset], &value, 2);
offset+=2;
}
// pass data and ptr, updates ptr automatically (by reference)
static __forceinline void write_uint8_t(uint8_t *data, size_t &offset, uint8_t value)
{
data[offset++] = value;
}
// pass data and ptr, updates ptr automatically (by reference)
static __forceinline void write_header(uint8_t *data, size_t &offset, const char *header)
{
data[offset++] = header[0];
data[offset++] = header[1];
data[offset++] = header[2];
data[offset++] = header[3];
}
// Case insensitive version of wcsstr
static wchar_t *wcsistr (const wchar_t *s1, const wchar_t *s2)
{
wchar_t *cp = (wchar_t*) s1;
wchar_t *s, *t, *endp;
wchar_t l, r;
endp = (wchar_t*)s1 + ( lstrlen(s1) - lstrlen(s2)) ;
while (cp && *cp && (cp <= endp))
{
s = cp;
t = (wchar_t*)s2;
while (s && *s && t && *t)
{
l = towupper(*s);
r = towupper(*t);
if (l != r)
break;
s++, t++;
}
if (*t == 0)
return cp;
cp = CharNext(cp);
}
return NULL;
}
//////////////////////////////////////////////////////////////////////
// iTunesSD1 - Classes for dealing with the iPodShuffle
//////////////////////////////////////////////////////////////////////
iTunesSD1::iTunesSD1()
{
}
iTunesSD1::~iTunesSD1()
{
}
long iTunesSD1::write(const iPod_mhlt::mhit_map_t *songs, unsigned char * data, const unsigned long datasize)
{
#ifdef IPODDB_PROFILER
profiler(iPodDB__iTunesSD_write);
#endif
const unsigned int numsongs = songs->size();
const unsigned int total_size = 18 + (numsongs * 558);
ASSERT(datasize >= total_size);
if(datasize < total_size)
return(-1);
long ptr=0;
put3(numsongs, &data[ptr]);
ptr+=3;
put3(0x010600, &data[ptr]);
ptr+=3;
put3(0x12, &data[ptr]);
ptr+=3;
put3(0, &data[ptr]);
ptr+=3;
put3(0, &data[ptr]);
ptr+=3;
put3(0, &data[ptr]);
ptr+=3;
iPod_mhlt::mhit_map_t::const_iterator begin = songs->begin();
iPod_mhlt::mhit_map_t::const_iterator end = songs->end();
for(iPod_mhlt::mhit_map_t::const_iterator it = begin; it != end; it++)
{
iPod_mhit *m = ((*it).second);
iTunesSD_Song song(m);
long ret = song.write(&data[ptr], datasize - ptr);
if (ret < 0)
return ret;
ptr += ret;
}
return(ptr);
}
iTunesSD_Song::iTunesSD_Song(const iPod_mhit *m) : size_total(0x22e), starttime(0), stoptime(0), volume(0x64), filetype(0), playflags(iTunesSD_Song::SHUFFLE)
{
memset(filename, 0, (SDSONG_FILENAME_LEN + 1) * sizeof(wchar_t));
iPod_mhod *mhod = m->FindString(MHOD_LOCATION);
ASSERT(mhod);
if(mhod)
{
// Convert from HFS format (:iPod_Control:Music:F00:filename) to quasi-FAT format (/iPod_Control/Music/F00/filename) filepaths
SetFilename(mhod->str);
wchar_t *w = filename;
while(w && *w != '\0')
{
if(*w == ':')
*w = '/';
w = CharNext(w);
}
SetStartTime(m->starttime);
SetStopTime(m->stoptime);
int volume = (int)m->volume;
// If Sound Check information is present, use that instead of volume
if(m->soundcheck != 0)
{
// This code converts SoundCheck back into a gain value, then into a -255 to 255 mhit::volume value
const double gain = -10.0 * log10(m->soundcheck / 1000.0);
volume = (int)(gain * 12.75); // XXX - this might not be the best way to convert the gain value...
}
if(volume < -255)
volume = -255;
else if(volume > 255)
volume = 255;
// Convert the volume value into a percentage for SetVolume
SetVolume((int)((double)volume / 2.55));
// To determine the filetype, first check the MHOD_FILETYPE type. If that isn't available, fallback to file extension
iPod_mhod *mtype = m->FindString(MHOD_FILETYPE);
if(mtype != NULL)
{
if(wcsistr(mtype->str, L"MPEG") != NULL || wcsistr(mtype->str, L"MP3") != NULL)
filetype = iTunesSD_Song::MP3;
else if(wcsistr(mtype->str, L"AAC") != NULL)
filetype = iTunesSD_Song::AAC;
else if(wcsistr(mtype->str, L"WAV") != NULL)
filetype = iTunesSD_Song::WAV;
}
if(filetype == 0)
{
if(wcsistr(mhod->str, L".mp3") != NULL)
filetype = iTunesSD_Song::MP3;
else if(wcsistr(mhod->str, L".m4a") != NULL || wcsistr(mhod->str, L".m4b") != NULL || wcsistr(mhod->str, L".m4p") != NULL)
filetype = iTunesSD_Song::AAC;
else if(wcsistr(mhod->str, L".wav") != NULL)
filetype = iTunesSD_Song::WAV;
}
ASSERT(filetype != 0);
if(filename == 0)
filetype = iTunesSD_Song::MP3; // Default to mp3
if(wcsistr(mhod->str, L".m4b") != NULL)
playflags = iTunesSD_Song::BOOKMARKABLE; // Only playback in normal mode
else
playflags = iTunesSD_Song::SHUFFLE; // Playable in normal/shuffle modes, but not bookmarkable
}
}
long iTunesSD_Song::write(unsigned char * data, const unsigned long datasize)
{
#ifdef IPODDB_PROFILER
profiler(iPodDB__iTunesSD_Song_write);
#endif
long ptr=0;
ASSERT(size_total == 0x22e);
ASSERT(filetype != 0);
put3(size_total, &data[ptr]);
ptr+=3;
put3(0x005aa501, &data[ptr]);
ptr+=3;
put3(starttime, &data[ptr]);
ptr+=3;
put3(0, &data[ptr]);
ptr+=3;
put3(0, &data[ptr]);
ptr+=3;
put3(stoptime, &data[ptr]);
ptr+=3;
put3(0, &data[ptr]);
ptr+=3;
put3(0, &data[ptr]);
ptr+=3;
put3(volume, &data[ptr]);
ptr+=3;
put3(filetype, &data[ptr]);
ptr+=3;
put3(0x200, &data[ptr]);
ptr+=3;
const unsigned int bufSize = (SDSONG_FILENAME_LEN + 1) * sizeof(wchar_t);
memcpy(&data[ptr], filename, bufSize);
ptr+=bufSize;
put3(playflags, &data[ptr]);
ptr+=3;
ASSERT(size_total == ptr);
return(ptr);
}
void iTunesSD_Song::SetFilename(const wchar_t *filename)
{
#ifdef IPODDB_PROFILER
profiler(iPodDB__iTunesStats_SetFilename);
#endif
ASSERT(filename != NULL);
if(filename == NULL)
return;
if(filename)
{
lstrcpyn(this->filename, filename, SDSONG_FILENAME_LEN);
}
else
{
memset(this->filename, 0, SDSONG_FILENAME_LEN * sizeof(wchar_t));
}
}
// Accepts values from -100 to 100, with 0 meaning no volume change
void iTunesSD_Song::SetVolume(const int percent)
{
int p = percent;
if(p > 100)
p = 100;
else if(p < -100)
p = -100;
// Volume ranges from 0 (-100%) to 100 (0%) to 200 (100%)
volume = (unsigned int)(percent + 100);
}
/* Shadow DB version 2 */
long iTunesSD2::write(const iPod_mhlt *songs, const iPod_mhlp *playlists, unsigned char * data, const unsigned long datasize)
{
uint32_t numsongs = songs->GetChildrenCount();
uint32_t numplaylists = playlists->GetChildrenCount();
size_t offset=0;
size_t ptr=0;
if (datasize < 64)
return -1;
write_header(data, ptr, "bdhs");
write_uint32_t(data, ptr, 0x02000003); /* also have seen 0x02010001, perhaps a DB version number? */
write_uint32_t(data, ptr, 64); /* length of header */
write_uint32_t(data, ptr, numsongs);
write_uint32_t(data, ptr, numplaylists); /* number of playlists */
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint8_t(data, ptr, 0); /* volume limit */
write_uint8_t(data, ptr, 1); /* voiceover */
write_uint16_t(data, ptr, 0);
write_uint32_t(data, ptr, numsongs); /* TODO number of tracks w/o podcasts and audiobooks*/
write_uint32_t(data, ptr, 64); /* track header offset */
write_uint32_t(data, ptr, 64+20 + numsongs*4+iTunesSD2_Song::header_size*numsongs); /* playlist header offset */
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
offset = 64;
uint32_t hths_header_size = 20+numsongs*4;
if (datasize - ptr < hths_header_size)
return -1;
write_header(data, ptr, "hths");
write_uint32_t(data, ptr, hths_header_size); /* header length */
write_uint32_t(data, ptr, numsongs);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
offset += hths_header_size;
/* positions for each track */
for (size_t i=0;i<numsongs;i++)
{
write_uint32_t(data, ptr, offset + iTunesSD2_Song::header_size * i);
}
/* write tracks */
for (uint32_t i=0;i<numsongs;i++)
{
iPod_mhit *m = songs->GetTrack(i);
long ret = iTunesSD2_Song::write(m, &data[ptr], datasize - ptr);
if (ret < 0)
return ret;
ptr += ret;
offset += ret;
}
uint32_t podcast_playlist_count=0;
for (size_t i=0;i<numplaylists;i++)
{
iPod_mhyp *p = playlists->GetPlaylist(i);
if (p->podcastflag)
podcast_playlist_count++;
}
uint32_t hphs_header_size = 20 + numplaylists*4;
if (datasize - ptr < hphs_header_size)
return -1;
write_header(data, ptr, "hphs");
write_uint32_t(data, ptr, hphs_header_size); /* header length */
write_uint32_t(data, ptr, numplaylists);
write_uint16_t(data, ptr, 0);
write_uint16_t(data, ptr, numplaylists-podcast_playlist_count); /* non-podcast playlists */
write_uint16_t(data, ptr, 1); /* master playlists */
write_uint16_t(data, ptr, numplaylists); /* non-audiobook playlists */
offset += hphs_header_size;
/* write offsets for each track */
for (size_t i=0;i<numplaylists;i++)
{
iPod_mhyp *p = playlists->GetPlaylist(i);
write_uint32_t(data, ptr, offset);
offset += p->GetMhipChildrenCount()*4 + 44;
}
iPod_mhyp *master_playlist = playlists->GetPlaylist(0);
/* write playlists */
for (size_t i=0;i<numplaylists;i++)
{
iPod_mhyp *p = playlists->GetPlaylist(i);
long ret = iTunesSD2_Playlist::write(master_playlist, p, &data[ptr], datasize - ptr);
if (ret < 0)
return ret;
ptr += ret;
}
return ptr;
}
uint32_t iTunesSD2_Song::header_size = 372;
long iTunesSD2_Song::write(const iPod_mhit *mhit, unsigned char *data, const unsigned long datasize)
{
if (datasize < header_size)
return -1;
size_t ptr=0;
write_header(data, ptr, "rths");
write_uint32_t(data, ptr, header_size); /* length of header */
write_uint32_t(data, ptr, mhit->starttime); /* start time, in milliseconds */
write_uint32_t(data, ptr, mhit->stoptime); /* stop time, in milliseconds */
write_uint32_t(data, ptr, mhit->volume); /* volume */
switch(mhit->filetype)
{
case FILETYPE_WAV:
write_uint32_t(data, ptr, iTunesSD_Song::WAV); /* file type */
break;
case FILETYPE_M4A:
case 0x4d344220:
case 0x4d345020:
write_uint32_t(data, ptr, iTunesSD_Song::AAC); /* file type */
break;
case FILETYPE_MP3:
default:
write_uint32_t(data, ptr, iTunesSD_Song::MP3); /* file type */
break;
}
iPod_mhod *mhod = mhit->FindString(MHOD_LOCATION);
char filename[256] = {0};
int converted = WideCharToMultiByte(CP_UTF8, 0, mhod->str, -1, filename, 256, 0, 0);
for (int i=0;i<converted;i++)
{
if (filename[i] == ':')
filename[i] = '/';
}
memcpy(&data[ptr], filename, converted);
ptr+=converted;
memset(&data[ptr], 0, 256-converted);
ptr+=256-converted;
write_uint32_t(data, ptr, mhit->bookmarktime); /* bookmark time */
write_uint8_t(data, ptr, 0); /* skip flag */
write_uint8_t(data, ptr, mhit->rememberPosition); /* remember playback position */
write_uint8_t(data, ptr, 0); /* part of gapless album */
write_uint8_t(data, ptr, 0);
write_uint32_t(data, ptr, mhit->pregap); /* pre-gap */
write_uint32_t(data, ptr, mhit->postgap); /* post-gap */
write_uint64_t(data, ptr, mhit->samplecount); /* number of samples */
write_uint32_t(data, ptr, mhit->gaplessData); /* gapless data */
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, mhit->album_id); /* album ID */
write_uint16_t(data, ptr, mhit->tracknum); /* track number */
write_uint16_t(data, ptr, mhit->cdnum); /* disc number */
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint64_t(data, ptr, mhit->dbid); /* dbid */
write_uint32_t(data, ptr, 0); /* artist ID */
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
return ptr;
}
long iTunesSD2_Playlist::write(const iPod_mhyp *master_playlist, const iPod_mhyp *playlist, unsigned char * data, const unsigned long datasize)
{
size_t ptr=0;
uint32_t tracks = playlist->GetMhipChildrenCount();
uint32_t header_size = 44 + tracks*4;
if (datasize < header_size)
return -1;
write_header(data, ptr, "lphs");
write_uint32_t(data, ptr, header_size); /* header length */
write_uint32_t(data, ptr, tracks); /* number of tracks */
/* number of music tracks TODO: special handling for master playlist */
if (playlist->podcastflag)
write_uint32_t(data, ptr, 0);
else
write_uint32_t(data, ptr, tracks);
write_uint64_t(data, ptr, playlist->playlistID); /* playlist ID */
/* playlist type */
if (playlist->podcastflag)
write_uint32_t(data, ptr, 3); /* podcast */
else if (playlist->hidden)
write_uint32_t(data, ptr, 1); /* master playlist */
else
write_uint32_t(data, ptr, 2); /* normal */
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
write_uint32_t(data, ptr, 0);
if (master_playlist == playlist)
{
for (uint32_t i=0;i<tracks;i++)
{
write_uint32_t(data, ptr, i);
}
}
else
{
for (uint32_t i=0;i<tracks;i++)
{
iPod_mhip *item = playlist->GetPlaylistEntry(i);
uint32_t master_index = master_playlist->FindPlaylistEntry(item->songindex);
assert(master_index != -1);
write_uint32_t(data, ptr, master_index);
}
}
return ptr;
}
+78
View File
@@ -0,0 +1,78 @@
#pragma once
#include <bfc/platform/types.h>
#include "iPodDB.h"
/* iPod shuffle Shadow Database code */
// iTunesSD (iPod Shuffle) Database Classes
class iTunesSD_Song;
class iTunesSD2_Song;
class iTunesSD1
{
public:
iTunesSD1();
~iTunesSD1();
long write(const iPod_mhlt::mhit_map_t *mhit, unsigned char * data, const unsigned long datasize);
};
class iTunesSD2
{
public:
long write(const iPod_mhlt *mhit, const iPod_mhlp *playlists, unsigned char * data, const unsigned long datasize);
};
#define SDSONG_FILENAME_LEN 260
class iTunesSD_Song
{
public:
iTunesSD_Song(const iPod_mhit *mhit);
enum FileType
{
MP3 = 0x01,
AAC = 0x02,
WAV = 0x04
};
enum PlayFlags
{
UNKNOWN = 0x000001, // Might do something special, but nothing has been observed so far
BOOKMARKABLE = 0x000100, // Any song that has flag is bookmarked
SHUFFLE = 0x010000 // Only songs that have this flag are available in shuffle playback mode
};
long write(unsigned char * data, const unsigned long datasize);
void SetFilename(const wchar_t *filename);
void SetStartTime(const double milliseconds) { starttime = (unsigned int)(milliseconds / 256.0); }
void SetStopTime(const double milliseconds) { stoptime = (unsigned int)(milliseconds / 256.0); }
void SetVolume(const int percent);
// These are also only 3 byte values
uint32_t size_total;
uint32_t starttime;
uint32_t stoptime;
uint32_t volume; // -100% = 0x0, 0% = 0x64 (100), 100% = 0xc8 (200)
uint32_t filetype; // 0x01 = MP3, 0x02 = AAC, 0x04 = WAV
wchar_t filename[SDSONG_FILENAME_LEN + 1]; // Equal to Windows' MAX_PATH, plus the trailing NULL (261 wide chars = 522 bytes)
unsigned int playflags;
};
class iTunesSD2_Song
{
public:
static long write(const iPod_mhit *mhit, unsigned char * data, const unsigned long datasize);
static uint32_t header_size;
};
class iTunesSD2_Playlist
{
public:
static long write(const iPod_mhyp *master_playlist, const iPod_mhyp *playlist, unsigned char * data, const unsigned long datasize);
};
+336
View File
@@ -0,0 +1,336 @@
//#define PLUGIN_NAME "Nullsoft iPod Plug-in"
#define PLUGIN_VERSION L"0.91"
#include "iPodDevice.h"
#include <Dbt.h>
#include "..\..\General\gen_ml/itemlist.h"
#include <api/service/waservicefactory.h>
#include "api.h"
#include "../nu/autoLock.h"
#include "deviceprovider.h"
#include <tataki/export.h>
#include <shlwapi.h>
int init();
void quit();
intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3);
extern PMPDevicePlugin plugin = {PMPHDR_VER,0,init,quit,MessageProc};
static DWORD WINAPI ThreadFunc_DeviceChange(LPVOID lpParam);
bool g_detectAll=false;
std::vector<iPodDevice*> iPods;
api_config *AGAVE_API_CONFIG=0;
api_memmgr *WASABI_API_MEMMGR=0;
api_albumart *AGAVE_API_ALBUMART=0;
api_threadpool *WASABI_API_THREADPOOL=0;
api_application *WASABI_API_APP=0;
api_devicemanager *AGAVE_API_DEVICEMANAGER = 0;
// wasabi based services for localisation support
api_language *WASABI_API_LNG = 0;
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
static Nullsoft::Utility::LockGuard connect_guard;
static DeviceProvider *deviceProvider = NULL;
static bool loading_devices[26] = {0,};
template <class api_T>
void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
{
if (plugin.service)
{
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
if (factory)
api_t = reinterpret_cast<api_T *>( factory->getInterface() );
}
}
template <class api_T>
void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
{
if (plugin.service && api_t)
{
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
if (factory)
factory->releaseInterface(api_t);
}
api_t = NULL;
}
static bool createBlankDatabase(wchar_t drive) {
wchar_t ipodtest[]={drive,L":\\iPod_Control\\iTunes\\iTunesDB"};
iPod_mhbd db;
BYTE data[4096] = {0};
long l = db.write(data,sizeof(data));
if(l <= 0) return false;
FILE* fh=_wfopen(ipodtest,L"wb");
if(!fh) return false;
if(fwrite(data,l,1,fh))
{
wchar_t ipodtest2[]={drive,L":\\iPod_Control\\iTunes\\firsttime"};
_wunlink(ipodtest2);
}
fclose(fh);
wchar_t music[] = {drive,L":\\iPod_Control\\Music"};
CreateDirectoryW(music,NULL);
return true;
}
bool ConnectDrive(wchar_t drive, bool connect)
{
bool result;
size_t index;
iPodDevice *device;
Nullsoft::Utility::AutoLock connect_lock(connect_guard);
// capitalize
if (drive >= L'a' && drive <= L'z')
drive = drive - 32;
// reject invalid drive letters
if (drive < L'A' || drive > L'Z')
return false;
if (false != loading_devices[drive-'A'])
return false;
loading_devices[drive-'A'] = true;
if (false != connect)
{
result = true;
char ipodtest[]= {(char)drive,":\\iPod_Control\\iTunes\\iTunesDB"};
if (GetFileAttributes(ipodtest) == INVALID_FILE_ATTRIBUTES)
{
char ipodtest2[]={(char)drive,":\\iPod_Control\\iTunes\\firsttime"};
if (GetFileAttributes(ipodtest2) == INVALID_FILE_ATTRIBUTES ||
false == createBlankDatabase(drive))
{
result = false;
}
}
if (false != result)
{
index = iPods.size();
while(index--)
{
device = iPods[index];
if(device->drive == drive)
break;
}
if((size_t)-1 == index)
{
iPodDevice *d = new iPodDevice((char)drive);
}
else
result = false;
}
}
else
{
result = false;
index = iPods.size();
while(index--)
{
device = iPods.at(index);
if (device->drive == drive)
{
SendNotifyMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)device,PMP_IPC_DEVICEDISCONNECTED);
iPods.erase(iPods.begin() + index);
delete device;
result = true;
break;
}
}
}
loading_devices[drive-'A'] = false;
return result;
}
static void autoDetectCallback(wchar_t driveW, UINT type)
{
if(false == g_detectAll && DRIVE_REMOVABLE != type)
return;
ConnectDrive(driveW, true);
}
int init()
{
wchar_t mlipod[MAX_PATH] = {0};
PathCombineW(mlipod, (LPCWSTR)SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_GETPLUGINDIRECTORYW), L"ml_ipod.dll");
FILE * f = _wfopen(mlipod, L"rb");
if (f) {
fclose(f);
return -1;
}
Tataki::Init(plugin.service);
ServiceBuild(AGAVE_API_CONFIG, AgaveConfigGUID);
ServiceBuild(WASABI_API_LNG, languageApiGUID);
ServiceBuild(WASABI_API_MEMMGR, memMgrApiServiceGuid);
ServiceBuild(AGAVE_API_ALBUMART, albumArtGUID);
ServiceBuild(WASABI_API_THREADPOOL, ThreadPoolGUID);
ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
ServiceBuild(AGAVE_API_DEVICEMANAGER, DeviceManagerGUID);
// need to have this initialised before we try to do anything with localisation features
WASABI_API_START_LANG(plugin.hDllInstance,PmpIPODLangGUID);
static wchar_t szDescription[256];
swprintf(szDescription, ARRAYSIZE(szDescription),
WASABI_API_LNGSTRINGW(IDS_NULLSOFT_IPOD_PLUGIN), PLUGIN_VERSION);
plugin.description = szDescription;
if (NULL != AGAVE_API_DEVICEMANAGER &&
NULL == deviceProvider)
{
if (SUCCEEDED(DeviceProvider::CreateInstance(&deviceProvider)) &&
FAILED(deviceProvider->Register(AGAVE_API_DEVICEMANAGER)))
{
deviceProvider->Release();
deviceProvider = NULL;
}
}
/* Our device shows up as a normal drive */
if (NULL == deviceProvider ||
FAILED(deviceProvider->BeginDiscovery(AGAVE_API_DEVICEMANAGER)))
{
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)autoDetectCallback,PMP_IPC_ENUM_ACTIVE_DRIVES);
}
return 0;
}
void quit()
{
ServiceRelease(AGAVE_API_CONFIG, AgaveConfigGUID);
ServiceRelease(WASABI_API_LNG, languageApiGUID);
ServiceRelease(WASABI_API_MEMMGR, memMgrApiServiceGuid);
ServiceRelease(AGAVE_API_ALBUMART, albumArtGUID);
ServiceRelease(WASABI_API_THREADPOOL, ThreadPoolGUID);
ServiceRelease(WASABI_API_APP, applicationApiServiceGuid);
ServiceRelease(AGAVE_API_DEVICEMANAGER, DeviceManagerGUID);
Tataki::Quit();
}
static char FirstDriveFromMask(ULONG unitmask) {
char i;
for(i=0; i<26; ++i) {
if(unitmask & 0x1) break;
unitmask = unitmask >> 1;
}
return (i+'A');
}
int wmDeviceChange(WPARAM wParam, LPARAM lParam)
{
if(wParam == DBT_DEVICEARRIVAL || wParam == DBT_DEVICEREMOVECOMPLETE)
{
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
if(lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)
{ // its a volume
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
if(0 == ((DBTF_MEDIA | DBTF_NET) & lpdbv->dbcv_flags) || g_detectAll)
{ // its not a network drive or a CD/floppy, game on!
unsigned long unitmask = lpdbv->dbcv_unitmask;
for (int i = 0; i < 26; i++)
{
if (0 != (0x1 & unitmask))
{
int p = (int)('A' + i);
if (DBT_DEVICEARRIVAL == wParam)
p += 0x10000;
ThreadFunc_DeviceChange((void*)(intptr_t)p);
unitmask = unitmask >> 1;
if (0 == unitmask)
break;
}
else
unitmask = unitmask >> 1;
}
}
}
}
return 0;
}
static DWORD WINAPI ThreadFunc_DeviceChange(LPVOID lpParam)
{
int p = (int)lpParam;
bool connect = p > 0x10000;
if(connect)
p -= 0x10000;
char drive = (char)p;
if(drive == 0)
return 0;
if(connect)
{ // something plugged in
ConnectDrive(drive, connect);
}
else
{ //something removed
size_t index;
index = iPods.size();
while(index--)
{
iPodDevice *device = iPods.at(index);
if (device->drive == drive)
{
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)device,PMP_IPC_DEVICEDISCONNECTED);
iPods.erase(iPods.begin() + index);
delete device;
break;
}
}
}
return 0;
}
intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3) {
switch(msg) {
case PMP_DEVICECHANGE:
return wmDeviceChange(param1,param2);
case PMP_NO_CONFIG:
return TRUE;
case PMP_CONFIG:
return 0;
}
return 0;
}
extern "C" {
__declspec( dllexport ) PMPDevicePlugin * winampGetPMPDevicePlugin(){return &plugin;}
__declspec( dllexport ) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg, int param) {
int i = iPods.size();
while(i-- > 0) iPods[i]->Close();
return PMP_PLUGIN_UNINSTALL_NOW;
}
};
+194
View File
@@ -0,0 +1,194 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// PNG
//
IDB_CLASSIC_16 PNG "resources\\apple_ipod_classic_16.png"
IDB_NANO1G_16 PNG "resources\\apple_ipod_nano_1g_16.png"
IDB_NANO2G_16 PNG "resources\\apple_ipod_nano_2g_16.png"
IDB_NANO3G_16 PNG "resources\\apple_ipod_nano_3g_16.png"
IDB_NANO4G_16 PNG "resources\\apple_ipod_nano_4g_16.png"
IDB_NANO5G_16 PNG "resources\\apple_ipod_nano_5g_16.png"
IDB_SHUFFLE1G_16 PNG "resources\\apple_ipod_shuffle_1g_16.png"
IDB_SHUFFLE2G_16 PNG "resources\\apple_ipod_shuffle_2g_16.png"
IDB_SHUFFLE3G_16 PNG "resources\\apple_ipod_shuffle_3g_16.png"
IDB_CLASSIC_160 PNG "resources\\apple_ipod_classic.png"
IDB_NANO1G_160 PNG "resources\\apple_ipod_nano_1g.png"
IDB_NANO2G_160 PNG "resources\\apple_ipod_nano_2g.png"
IDB_NANO3G_160 PNG "resources\\apple_ipod_nano_3g.png"
IDB_NANO4G_160 PNG "resources\\apple_ipod_nano_4g.png"
IDB_NANO5G_160 PNG "resources\\apple_ipod_nano_5g.png"
IDB_SHUFFLE1G_160 PNG "resources\\apple_ipod_shuffle_1g.png"
IDB_SHUFFLE2G_160 PNG "resources\\apple_ipod_shuffle_2g.png"
IDB_SHUFFLE3G_160 PNG "resources\\apple_ipod_shuffle_3g.png"
IDB_SHUFFLE4G_160 PNG "resources\\apple_ipod_shuffle_4g.png"
IDB_SHUFFLE4G_16 PNG "resources\\apple_ipod_shuffle_4g_16.png"
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_CONFIG DIALOGEX 0, 0, 264, 226
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
GROUPBOX "Gapless Playback",IDC_STATIC,4,3,255,44
LTEXT "Some iPods support the gapless playback of files.\nTo enable this, Winamp needs to scan the files on your iPod. Click ""Scan"" to begin this process.",IDC_STATIC,12,14,179,24
PUSHBUTTON "Scan",IDC_SCAN,201,19,50,14
GROUPBOX "Album Art",IDC_STATIC_ARTGROUP,4,54,255,30,NOT WS_VISIBLE
CONTROL "Add album art to tracks during transfer",IDC_CHECK_USEART,
"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,9,67,141,10
END
IDD_GAPSCAN DIALOGEX 0, 0, 186, 55
STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Scanning for gapless playback information"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "Scanning...",IDC_CAPTION,7,7,172,8
CONTROL "",IDC_PROGRESS1,"msctls_progress32",WS_BORDER,7,17,172,14
PUSHBUTTON "Scan in Background",IDC_BG,21,34,69,14
PUSHBUTTON "Stop Scan",IDCANCEL,95,34,50,14
END
IDD_SELECTIPODTYPE DIALOGEX 0, 0, 186, 140
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_TOPMOST | WS_EX_APPWINDOW
CAPTION "Select iPod Type"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
LTEXT "In order to support some new features, we need to know which iPod model you have.",IDC_STATIC,7,7,172,17
LTEXT "My iPod model is:",IDC_IPODINFO,7,27,172,8
CONTROL "iPod Touch",IDC_RADIO6,"Button",BS_AUTORADIOBUTTON,7,40,51,10
CONTROL "iPod Classic",IDC_RADIO7,"Button",BS_AUTORADIOBUTTON,7,50,53,10
CONTROL "iPod Nano (widescreen)",IDC_RADIO8,"Button",BS_AUTORADIOBUTTON,7,59,91,10
CONTROL "iPod Shuffle",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,7,69,54,10
CONTROL "iPod Photo",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,7,79,50,10
CONTROL "iPod Video",IDC_RADIO3,"Button",BS_AUTORADIOBUTTON,7,89,49,10
CONTROL "iPod Nano",IDC_RADIO4,"Button",BS_AUTORADIOBUTTON,7,99,48,10
CONTROL "Other",IDC_RADIO5,"Button",BS_AUTORADIOBUTTON,7,109,35,10
DEFPUSHBUTTON "OK",IDOK,67,119,50,14,WS_DISABLED
PUSHBUTTON "Cancel",IDCANCEL,127,119,52,14
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_GAPSCAN, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 48
END
IDD_SELECTIPODTYPE, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
TOPMARGIN, 7
BOTTOMMARGIN, 133
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_NULLSOFT_IPOD_PLUGIN "Nullsoft iPod Device Plug-in v%s"
65535 "{C2EE3DA5-B29B-42a0-AB5E-B202393435D6}"
END
STRINGTABLE
BEGIN
IDS_CANNOT_OPEN_FILE "Cannot open file"
IDS_CANNOT_CREATE_FILE "Cannot create file"
IDS_TRANSFERRING_PERCENT "Transferring %d%%"
IDS_CANCELLED "Cancelled"
IDS_DONE "Done"
IDS_TRANSFER_FAILED "Transfer failed"
IDS_IPOD_LOADING "iPod Loading..."
IDS_FAILED_TO_EJECT_IPOD
"Failed to Eject iPod. Is something else using it?"
IDS_ERROR "Error"
IDS_INVALID_TRACK "Invalid Track"
IDS_SCANNING "Scanning..."
IDS_ADVANCED "Advanced"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
@@ -0,0 +1,75 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29424.173
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pmp_ipod", "pmp_ipod.vcxproj", "{54C393C2-5A0A-497F-930B-DA5316351B00}"
ProjectSection(ProjectDependencies) = postProject
{DABE6307-F8DD-416D-9DAC-673E2DECB73F} = {DABE6307-F8DD-416D-9DAC-673E2DECB73F}
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1} = {D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}
{5ED1729B-EA41-4163-9506-741A8B76F625} = {5ED1729B-EA41-4163-9506-741A8B76F625}
{255B68B5-7EF8-45EF-A675-2D6B88147909} = {255B68B5-7EF8-45EF-A675-2D6B88147909}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bfc", "..\Wasabi\bfc\bfc.vcxproj", "{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "plist", "..\plist\plist.vcxproj", "{5ED1729B-EA41-4163-9506-741A8B76F625}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tataki", "..\tataki\tataki.vcxproj", "{255B68B5-7EF8-45EF-A675-2D6B88147909}"
ProjectSection(ProjectDependencies) = postProject
{DABE6307-F8DD-416D-9DAC-673E2DECB73F} = {DABE6307-F8DD-416D-9DAC-673E2DECB73F}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nsutil", "..\nsutil\nsutil.vcxproj", "{DABE6307-F8DD-416D-9DAC-673E2DECB73F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{54C393C2-5A0A-497F-930B-DA5316351B00}.Debug|Win32.ActiveCfg = Debug|Win32
{54C393C2-5A0A-497F-930B-DA5316351B00}.Debug|Win32.Build.0 = Debug|Win32
{54C393C2-5A0A-497F-930B-DA5316351B00}.Debug|x64.ActiveCfg = Debug|x64
{54C393C2-5A0A-497F-930B-DA5316351B00}.Debug|x64.Build.0 = Debug|x64
{54C393C2-5A0A-497F-930B-DA5316351B00}.Release|Win32.ActiveCfg = Release|Win32
{54C393C2-5A0A-497F-930B-DA5316351B00}.Release|Win32.Build.0 = Release|Win32
{54C393C2-5A0A-497F-930B-DA5316351B00}.Release|x64.ActiveCfg = Release|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.ActiveCfg = Debug|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|Win32.Build.0 = Debug|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Debug|x64.ActiveCfg = Debug|x64
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.ActiveCfg = Release|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|Win32.Build.0 = Release|Win32
{D0EC862E-DDDD-4F4F-934F-B75DC9062DC1}.Release|x64.ActiveCfg = Release|x64
{5ED1729B-EA41-4163-9506-741A8B76F625}.Debug|Win32.ActiveCfg = Debug|Win32
{5ED1729B-EA41-4163-9506-741A8B76F625}.Debug|Win32.Build.0 = Debug|Win32
{5ED1729B-EA41-4163-9506-741A8B76F625}.Debug|x64.ActiveCfg = Debug|x64
{5ED1729B-EA41-4163-9506-741A8B76F625}.Release|Win32.ActiveCfg = Release|Win32
{5ED1729B-EA41-4163-9506-741A8B76F625}.Release|Win32.Build.0 = Release|Win32
{5ED1729B-EA41-4163-9506-741A8B76F625}.Release|x64.ActiveCfg = Release|x64
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|Win32.ActiveCfg = Debug|Win32
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|Win32.Build.0 = Debug|Win32
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|x64.ActiveCfg = Debug|x64
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Debug|x64.Build.0 = Debug|x64
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|Win32.ActiveCfg = Release|Win32
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|Win32.Build.0 = Release|Win32
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|x64.ActiveCfg = Release|x64
{255B68B5-7EF8-45EF-A675-2D6B88147909}.Release|x64.Build.0 = Release|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.ActiveCfg = Debug|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|Win32.Build.0 = Debug|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.ActiveCfg = Debug|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Debug|x64.Build.0 = Debug|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.ActiveCfg = Release|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|Win32.Build.0 = Release|Win32
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.ActiveCfg = Release|x64
{DABE6307-F8DD-416D-9DAC-673E2DECB73F}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FC646532-2050-40A5-A2AB-F699F1C071C4}
EndGlobalSection
EndGlobal
@@ -0,0 +1,355 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{54C393C2-5A0A-497F-930B-DA5316351B00}</ProjectGuid>
<RootNamespace>pmp_ipod</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\Wasabi;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ML_ex_EXPORTS;_UNICODE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4018;4244;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<GenerateMapFile>false</GenerateMapFile>
<MapExports>false</MapExports>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>true</DataExecutionPrevention>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\Wasabi;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;ML_ex_EXPORTS;_UNICODE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4018;4244;4302;4311;4267;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<GenerateMapFile>false</GenerateMapFile>
<MapExports>false</MapExports>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>true</RandomizedBaseAddress>
<DataExecutionPrevention>true</DataExecutionPrevention>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\Wasabi;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ML_ex_EXPORTS;_UNICODE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4018;4244;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\Wasabi;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;ML_ex_EXPORTS;_UNICODE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4018;4244;4302;4311;4267;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\plist\plist.vcxproj">
<Project>{5ed1729b-ea41-4163-9506-741a8b76f625}</Project>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\tataki\tataki.vcxproj">
<Project>{255b68b5-7ef8-45ef-a675-2d6b88147909}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\Wasabi\bfc\bfc.vcxproj">
<Project>{d0ec862e-dddd-4f4f-934f-b75dc9062dc1}</Project>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
<ReferenceOutputAssembly>true</ReferenceOutputAssembly>
</ProjectReference>
<ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\General\gen_ml\itemlist.cpp" />
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp" />
<ClCompile Include="deviceprovider.cpp" />
<ClCompile Include="eject.cpp" />
<ClCompile Include="filecopy.cpp" />
<ClCompile Include="hash58.cpp" />
<ClCompile Include="iPodArtworkDB.cpp" />
<ClCompile Include="iPodDB.cpp" />
<ClCompile Include="iPodDevice.cpp" />
<ClCompile Include="iPodInfo.cpp" />
<ClCompile Include="iPodSD.cpp" />
<ClCompile Include="main.cpp">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;ML_ex_EXPORTS</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">WIN64;_DEBUG;_WINDOWS;_MBCS;_USRDLL;ML_ex_EXPORTS</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;ML_ex_EXPORTS</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">WIN64;NDEBUG;_WINDOWS;_MBCS;_USRDLL;ML_ex_EXPORTS</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="sha1.c" />
<ClCompile Include="SysInfoXML.cpp" />
<ClCompile Include="yail.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\General\gen_ml\itemlist.h" />
<ClInclude Include="..\..\General\gen_ml\ml.h" />
<ClInclude Include="..\..\Library\ml_pmp\pmp.h" />
<ClInclude Include="..\..\..\nu\Map.h" />
<ClInclude Include="api.h" />
<ClInclude Include="deviceprovider.h" />
<ClInclude Include="hash58.h" />
<ClInclude Include="iPodArtworkDB.h" />
<ClInclude Include="iPodDB.h" />
<ClInclude Include="iPodDevice.h" />
<ClInclude Include="iPodInfo.h" />
<ClInclude Include="iPodSD.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="sha1.h" />
<ClInclude Include="yail.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_ipod.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="deviceprovider.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="eject.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="filecopy.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="hash58.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="iPodArtworkDB.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="iPodDB.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="iPodDevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="iPodInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="iPodSD.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="sha1.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SysInfoXML.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="yail.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\itemlist.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="deviceprovider.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hash58.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iPodArtworkDB.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iPodDB.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iPodDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iPodInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="iPodSD.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="sha1.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="yail.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\General\gen_ml\itemlist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\nu\Map.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\General\gen_ml\ml.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\Library\ml_pmp\pmp.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{8a27dfc8-8c21-4608-a4b0-2de0009d3411}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{72f38cc1-6101-41e6-a08e-3583fa56c3ba}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{b8889dfc-5b23-471a-821f-74e6540a3df2}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_ipod.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
+71
View File
@@ -0,0 +1,71 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by pmp_ipod1.rc
//
#define IDS_CANNOT_OPEN_FILE 1
#define IDS_CANNOT_CREATE_FILE 2
#define IDS_TRANSFERRING_PERCENT 3
#define IDS_CANCELLED 4
#define IDS_DONE 5
#define IDS_TRANSFER_FAILED 6
#define IDS_IPOD_LOADING 7
#define IDS_FAILED_TO_EJECT_IPOD 8
#define IDS_ERROR 9
#define IDS_INVALID_TRACK 10
#define IDS_SCANNING 11
#define IDS_STRING12 12
#define IDS_ADVANCED 12
#define IDD_CONFIG 102
#define IDD_GAPSCAN 103
#define IDD_DIALOG1 106
#define IDD_SELECTIPODTYPE 106
#define IDB_CLASSIC_16 110
#define IDB_NANO1G_16 111
#define IDB_NANO2G_16 112
#define IDB_NANO3G_16 113
#define IDB_NANO4G_16 114
#define IDB_NANO5G_16 115
#define IDB_SHUFFLE1G_16 116
#define IDB_SHUFFLE2G_16 117
#define IDB_SHUFFLE3G_16 118
#define IDB_CLASSIC_160 119
#define IDB_NANO1G_160 120
#define IDB_NANO2G_160 121
#define IDB_NANO3G_160 122
#define IDB_NANO4G_160 123
#define IDB_NANO5G_160 124
#define IDB_SHUFFLE1G_160 125
#define IDB_SHUFFLE2G_160 126
#define IDB_PNG9 127
#define IDB_SHUFFLE3G_160 127
#define IDB_SHUFFLE4G_160 128
#define IDB_PNG1 129
#define IDB_SHUFFLE4G_16 129
#define IDC_SCAN 1001
#define IDC_PROGRESS1 1002
#define IDC_CAPTION 1003
#define IDC_BUTTON1 1004
#define IDC_BG 1004
#define IDC_RADIO1 1005
#define IDC_RADIO2 1006
#define IDC_RADIO3 1007
#define IDC_RADIO4 1008
#define IDC_IPODINFO 1009
#define IDC_RADIO5 1010
#define IDC_CHECK_USEART 1011
#define IDC_RADIO6 1011
#define IDC_RADIO7 1012
#define IDC_STATIC_ARTGROUP 1013
#define IDC_RADIO8 1013
#define IDS_NULLSOFT_IPOD_PLUGIN 65534
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 131
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1014
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

+240
View File
@@ -0,0 +1,240 @@
/*
SHA-1 in C
By Steve Reid <steve@edmweb.com>
100% Public Domain
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#define LITTLE_ENDIAN /* This should be #define'd if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#include <stdio.h>
#include <string.h>
typedef struct {
unsigned long state[5];
unsigned long count[2];
unsigned char buffer[64];
} SHA1_CTX;
void SHA1Transform(unsigned long state[5], unsigned char buffer[64]);
void SHA1Init(SHA1_CTX* context);
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifdef LITTLE_ENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1Transform(unsigned long state[5], unsigned char buffer[64])
{
unsigned long a, b, c, d, e;
typedef union {
unsigned char c[64];
unsigned long l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
/*
printf("SHA1Transform:\n");
for (k = 0; k < 4; k++) {
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
printf("%02X", buffer[k*16+i*4+j]);
}
putchar(' ');
}
putchar('\n');
}
printf("SHA1Transform (translated):\n");
for (k = 0; k < 4; k++) {
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
long x = buffer[k*16+i*4+j] & 0xFF;
printf("%02X", cryptTable[x] & 0xFF);
}
putchar(' ');
}
putchar('\n');
}
*/
#ifdef SHA1HANDSOFF
static unsigned char workspace[64];
block = (CHAR64LONG16*)workspace;
memcpy(block, buffer, 64);
#else
block = (CHAR64LONG16*)buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
}
/* SHA1Init - Initialize new context */
void SHA1Init(SHA1_CTX* context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len)
{
unsigned int i, j;
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
}
/* Add padding and return the message digest. */
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
{
unsigned long i, j;
unsigned char finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
SHA1Update(context, (unsigned char *)"\200", 1);
while ((context->count[0] & 504) != 448) {
SHA1Update(context, (unsigned char *)"\0", 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
for (i = 0; i < 20; i++) {
digest[i] = (unsigned char)
((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
/* Wipe variables */
i = j = 0;
memset(context->buffer, 0, 64);
memset(context->state, 0, 20);
memset(context->count, 0, 8);
memset(&finalcount, 0, 8);
#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */
SHA1Transform(context->state, context->buffer);
#endif
}
/*************************************************************/
/*
int main(int argc, char** argv)
{
int i, j;
SHA1_CTX context;
unsigned char digest[20], buffer[16384];
FILE* file;
if (argc > 2) {
puts("Public domain SHA-1 implementation - by Steve Reid <steve@edmweb.com>");
puts("Produces the SHA-1 hash of a file, or stdin if no file is specified.");
exit(0);
}
if (argc < 2) {
file = stdin;
}
else {
if (!(file = fopen(argv[1], "rb"))) {
fputs("Unable to open file.", stderr);
exit(-1);
}
}
SHA1Init(&context);
while (!feof(file)) { /* note: what if ferror(file)
i = fread(buffer, 1, 16384, file);
SHA1Update(&context, buffer, i);
}
SHA1Final(digest, &context);
fclose(file);
for (i = 0; i < 5; i++) {
for (j = 0; j < 4; j++) {
printf("%02X", digest[i*4+j]);
}
putchar(' ');
}
putchar('\n');
exit(0);
}
*/
+9
View File
@@ -0,0 +1,9 @@
typedef struct {
unsigned long state[5];
unsigned long count[2];
unsigned char buffer[64];
} SHA1_CTX;
extern "C" void SHA1Init(SHA1_CTX* context);
extern "C" void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len);
extern "C" void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+39
View File
@@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../../../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,91,0,0
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp Portable Device Plug-in"
VALUE "FileVersion", "0,91,0,0"
VALUE "InternalName", "Nullsoft iPod Device"
VALUE "LegalCopyright", "Copyright © 2006-2023 Winamp SA"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "pmp_ipod.dll"
VALUE "ProductName", "Winamp"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
+114
View File
@@ -0,0 +1,114 @@
#include "iPodDevice.h"
#include <stdlib.h>
#include <memory.h>
#include <api/service/waservicefactory.h>
#include <api/service/svcs/svc_imgload.h>
#include "api.h"
#include <tataki/export.h>
#include "yail.h"
extern PMPDevicePlugin plugin;
static void recTransform (RGB565 *destination, RGB565 *source, int width, int height, int row_stride);
static __forceinline ARGB32 pixto32bit(RGB565 pix0, int format) {
unsigned long pix = pix0;
if(format == RGB_565)
return (ARGB32)(((pix & 0x001F) << 3) | ((pix & 0x07E0) << 5) | ((pix & 0xF800) << 8) | 0xff000000);
else // format == RGB_555. Ignore alpha channel.
return (ARGB32)(((pix & 0x001F) << 3) | ((pix & 0x03E0) << 6) | ((pix & 0x7C00) << 9) | 0xff000000);
}
static __forceinline RGB565 pixto16bit(ARGB32 pix, int format) {
// 10987654321098765432109876543210
// ARGB32 is AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB
// RGB565 is RRRRRGGGGGGBBBBB
// RGB555 is ARRRRRGGGGGBBBBB
if(format == RGB_565)
return (RGB565)( ((pix >> 8) & 0xF800) | ((pix >> 5) & 0x07E0) | ((pix >> 3) & 0x001F) );
else // format == RGB_555. set A to 1 for now.
return (RGB565)( 0x8000 | ((pix >> 9) & 0x7C00) | ((pix >> 6) & 0x03E0) | ((pix >> 3) & 0x001F) );
}
Image::Image(const ARGB32 * d, int w, int h) : width(w), height(h) {
int size = sizeof(ARGB32)*w*h;
data = (ARGB32*)calloc(size,1);
memcpy(data,d,size);
}
#define ALIGN(size, boundary) ((((boundary) - ((size) % (boundary))) % (boundary)) + (size))
Image::Image(const RGB565 * d, int w, int h, int format, int alignRowBytes, int alignImageBytes) : width(w), height(h) {
data = (ARGB32*)calloc(w*h*sizeof(ARGB32),1);
int rowgap = (ALIGN(sizeof(RGB565) * width, alignRowBytes) / sizeof(RGB565)) - width;
int p=0, q=0;
for(int j=0; j<height; j++)
{
for(int i=0; i<width; i++)
{
data[p++] = pixto32bit(d[q++], format);
}
q += rowgap;
}
}
Image::~Image() {
if(data) free(data); data=0;
}
void Image::exportToRGB565(RGB565* d_, int format, int alignRowBytes, int alignImageBytes) const {
int p=0, q=0;
int rowgap = (ALIGN(sizeof(RGB565) * width, alignRowBytes) / sizeof(RGB565)) - width;
RGB565* d;
if(format == RGB_555_REC)
{
int l = get16BitSize(width, height, alignRowBytes, alignImageBytes);
d = (RGB565*)calloc(l, 1);
}
else
d = d_;
for(int j=0; j<height; j++)
{
for(int i=0; i<width; i++)
{
d[p++] = pixto16bit(data[q++], format);
}
p += rowgap;
}
if(format == RGB_555_REC)
{ // do wierd transform
recTransform(d_, d, width, height, width + rowgap);
free(d);
}
}
void Image::exportToARGB32(ARGB32* d) const {
memcpy(d,data,sizeof(ARGB32)*width*height);
}
int Image::get16BitSize(int width, int height, int alignRowBytes, int alignImageBytes) {
int rowSize = ALIGN(sizeof(RGB565) * width, alignRowBytes);
return ALIGN(rowSize * height, alignImageBytes);
}
static void recTransform (RGB565 *destination, RGB565 *source, int width, int height, int row_stride)
{
if (width == 1)
{
*destination = *source;
}
else
{
recTransform(destination, source, width/2, height/2, row_stride);
recTransform(destination + (width/2)*(height/2), source + (height/2)*row_stride, width/2, height/2, row_stride);
recTransform(destination + 2*(width/2)*(height/2), source + width/2, width/2, height/2, row_stride);
recTransform(destination + 3*(width/2)*(height/2), source + (height/2)*row_stride + width/2, width/2, height/2, row_stride);
}
}
+25
View File
@@ -0,0 +1,25 @@
#ifndef _YAIL_H_
#define _YAIL_H_
// yet another image library. Because everything else SUCKS. Fact.
typedef unsigned short RGB565;
class Image {
public:
Image(const ARGB32 * data, int w, int h);
Image(const RGB565 * data, int w, int h, int format, int alignRowBytes, int alignImageBytes);
~Image();
void exportToRGB565(RGB565* data, int format, int alignRowBytes, int alignImageBytes) const;
void exportToARGB32(ARGB32* data) const;
ARGB32 * getData() {return data;}
int getWidth() const {return width;}
int getHeight() const {return height;}
int get16BitSize(int alignRowBytes, int alignImageBytes) { return get16BitSize(width,height,alignRowBytes, alignImageBytes); }
static int get16BitSize(int width, int height, int alignRowBytes, int alignImageBytes);
protected:
ARGB32 *data;
int width,height;
};
#endif //_YAIL_H_
+714
View File
@@ -0,0 +1,714 @@
#include "NJBDevice.h"
#include "../nu/AutoWide.h"
#include "../nu/AutoChar.h"
HWND CreateDummyWindow();
extern HWND mainMessageWindow;
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 void FillSongFromMeta(BYTE * buf,Song * song) {
BYTE * ptr = buf;
short count = 0;
short type = 0;
short NameLen = 0;
long DataLen = 0;
long lData;
memcpy(&count, ptr, sizeof(short));
ptr += sizeof(short);
for(int i=0; i<count; i++)
{
memcpy(&type, ptr, sizeof(short));
ptr += sizeof(short);
memcpy(&NameLen, ptr, sizeof(short));
ptr += sizeof(short);
memcpy(&DataLen, ptr, sizeof(long));
ptr += sizeof(long);
char itemname[MAX_PATH] = {0};
memcpy(itemname, ptr, NameLen);
itemname[NameLen]=0;
ptr += NameLen;
if(type == 1) { // binary
memcpy(&lData, ptr, min(DataLen,4));
if (!_stricmp(itemname,LENGTH)) song->length = lData * 1000;
else if (!_stricmp(itemname,FILESIZE)) song->size = lData;
else if (!_stricmp(itemname,TRACKNUM)) song->track = lData;
else if (!_stricmp(itemname,YEAR)) song->year = lData;
else if (!_stricmp(itemname,TRACKID)) song->trackid = lData;
} else if(type == 2) { // unicode
if (!_stricmp(itemname,TITLE)) lstrcpyn(song->title,(WCHAR*)ptr,min((DataLen+2)/2,fieldlen));
else if (!_stricmp(itemname,ARTIST)) lstrcpyn(song->artist,(WCHAR*)ptr,min((DataLen+2)/2,fieldlen));
else if (!_stricmp(itemname,ALBUM)) lstrcpyn(song->album,(WCHAR*)ptr,min((DataLen+2)/2,fieldlen));
else if (!_stricmp(itemname,GENRE)) lstrcpyn(song->genre,(WCHAR*)ptr,min((DataLen+2)/2,fieldlen));
} else if(type == 0) { // ASCII
if (!_stricmp(itemname,CODEC)) {
int l=min(sizeof(song->codec)-1,DataLen);
memcpy(song->codec,ptr,l);
song->codec[l]=0;
}
}
ptr += DataLen;
}
}
static bool GetSong(DAPSDK_ID * item, long id, Song * song) {
long size;
if(m_pCTJukebox2->GetItemAttribute(id,(IUnknown*)item,0,&size,NULL) != S_OK) return false;
BYTE * buf = (BYTE*)calloc(size,sizeof(BYTE));
if(!buf) return false;
if(m_pCTJukebox2->GetItemAttribute(id,(IUnknown*)item,size,&size,(IUnknown*)buf) != S_OK) { free(buf); return false; }
FillSongFromMeta(buf,song);
free(buf);
return true;
}
static int song_sortfunc(const void *elem1, const void *elem2) {
Song *a=(Song *)*(void **)elem1;
Song *b=(Song *)*(void **)elem2;
return a->trackid - b->trackid;
}
static Song *BinaryChopFind(int id,Playlist * mpl) {
Song s;
s.trackid=id;
Song * d = &s;
Song ** ret = (Song**)bsearch(&d,mpl->songs.GetAll(),mpl->songs.GetSize(),sizeof(void*),song_sortfunc);
return ret?*ret:NULL;
}
static bool GetPlaylist(long id, DAPSDK_ID * item,Playlist * pl, Playlist * mpl)
{
pl->dirty=false;
pl->plid = item->lID;
lstrcpyn(pl->name,item->bstrName,fieldlen);
SysFreeString(item->bstrName);
DAPSDK_ID song;
HRESULT hr = m_pCTJukebox2->FindFirstItem(id,(IUnknown*)item,(IUnknown*)&song);
while(hr == S_OK) {
Song * s = BinaryChopFind(song.lID,mpl);
if(s) pl->songs.Add(s);
hr = m_pCTJukebox2->FindNextItem(id,(IUnknown*)item,(IUnknown*)&song);
}
return true;
}
NJBDevice::NJBDevice(long id) : transcoder(NULL)
{
InitializeCriticalSection(&csRevTransfer);
InitializeCriticalSection(&csTransfer);
devices.Add(this);
pmpDeviceLoading load;
load.dev = this;
load.UpdateCaption = NULL;
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)&load,PMP_IPC_DEVICELOADING);
if(load.UpdateCaption) {
load.UpdateCaption(WASABI_API_LNGSTRINGW(IDS_NJB_LOADING),load.context);
}
this->id = id;
transferQueueLength = 0;
messageWindow = CreateDummyWindow();
m_pCTJukebox2->SetCallbackWindow2(id,(long)messageWindow);
BYTE * ptr = NULL;
if(m_pCTJukebox2->GetDeviceProperties(id,kDeviceSerialNumberValue,(IUnknown*)ptr) == S_OK) {
memcpy(serial,ptr,16);
//free(ptr);
}
DAPSDK_ID item,parent,root;
Playlist * mpl = new Playlist;
BSTR name=NULL;
m_pCTJukebox2->GetDeviceProperties(id,kDeviceNameString,(IUnknown*)&name);
lstrcpyn(mpl->name,name?name:L"Creative Jukebox",fieldlen);
SysFreeString(name);
// search for tracks...
parent.lID = ALLTRACKSKEY;
parent.lType = kAudioTrackType;
HRESULT hr = m_pCTJukebox2->FindFirstItem(id,(IUnknown*)&parent,(IUnknown*)&item);
while(hr == S_OK) {
// add track
Song * song = new Song;
if(GetSong(&item,id,song)) {
mpl->songs.Add(song);
song->trackid = item.lID;
}
else delete song;
hr = m_pCTJukebox2->FindNextItem(id,(IUnknown*)&parent,(IUnknown*)&item);
}
qsort(mpl->songs.GetAll(),mpl->songs.GetSize(),sizeof(void*),song_sortfunc); // sort the master playlist by trackid, so we can find stuff later using binary chop
playlists.Add(mpl);
// search for playlists...
hr = m_pCTJukebox2->FindFirstRootItem(id,(IUnknown*)&root);
while(hr == S_OK) {
if(_wcsicmp(root.bstrName,L"PLAY LISTS")==0) {
playlistRoot.bstrName = L"PLAY LISTS";
playlistRoot.lID = root.lID;
playlistRoot.lType = root.lType;
HRESULT hr = m_pCTJukebox2->FindFirstParentItem(id,(IUnknown*)&root,(IUnknown*)&parent);
while(hr == S_OK) {
Playlist * pl = new Playlist;
if(GetPlaylist(id,&parent,pl,mpl)) playlists.Add(pl);
else delete pl;
hr = m_pCTJukebox2->FindNextParentItem(id,(IUnknown*)&root,(IUnknown*)&parent);
}
}
SysFreeString(root.bstrName);
hr = m_pCTJukebox2->FindNextRootItem(id,(IUnknown*)&root);
}
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICECONNECTED);
//transcoder = NULL;
transcoder = (Transcoder*)SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_GET_TRANSCODER);
if(transcoder) {
transcoder->AddAcceptableFormat(L"mp3");
//transcoder->AddAcceptableFormat(L"wav");
transcoder->AddAcceptableFormat(L"wma");
}
}
NJBDevice::~NJBDevice()
{
m_pCTJukebox2->SetCallbackWindow2(id, (long)mainMessageWindow);
DestroyWindow(messageWindow);
messageWindow = NULL;
Playlist * mpl = (Playlist *)playlists.Get(0);
int l = mpl->songs.GetSize();
for(int i=0; i<l; i++) delete (Song *)mpl->songs.Get(i);
l = playlists.GetSize();
for(int i=0; i<l; i++) delete (Playlist *)playlists.Get(i);
for(int i=0; i<devices.GetSize(); i++) if(devices.Get(i) == this) { devices.Del(i); break; }
DeleteCriticalSection(&csRevTransfer);
DeleteCriticalSection(&csTransfer);
if(transcoder) SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)transcoder,PMP_IPC_RELEASE_TRANSCODER);
}
__int64 NJBDevice::getDeviceCapacityAvailable() {
DAPSDK_STORAGE_INFO s;
ULARGE_INTEGER ret;
m_pCTJukebox2->GetDeviceProperties(id,kStorageInfoStruct,(IUnknown*)&s);
ret.LowPart = s.freeL;
ret.HighPart = s.freeH;
return ret.QuadPart;
}
__int64 NJBDevice::getDeviceCapacityTotal() {
DAPSDK_STORAGE_INFO s;
ULARGE_INTEGER ret;
m_pCTJukebox2->GetDeviceProperties(id,kStorageInfoStruct,(IUnknown*)&s);
ret.LowPart = s.totalL;
ret.HighPart = s.totalH;
return ret.QuadPart;
}
void NJBDevice::Eject() {
Close();
}
void NJBDevice::Close()
{
commitChanges();
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICEDISCONNECTED);
if(devices.GetSize() == 1)
m_pCTJukebox2->SetCallbackWindow2(0,(long)mainMessageWindow);
delete this;
}
static BYTE * setAttrib(BYTE * ptr,short type, char * name, BYTE * data, int datalen) {
short namelen = (short)strlen(name);
memcpy(ptr,&type,2); ptr += 2;
memcpy(ptr,&namelen,2); ptr += 2;
memcpy(ptr,&datalen,4); ptr += 4;
memcpy(ptr,name,namelen); ptr += namelen;
memcpy(ptr,data,datalen); ptr += datalen;
return ptr;
}
static BYTE * makeMetaFromItemRecord(itemRecordW * item, wchar_t * file, long * size) {
char codec[4]="WAV";
wchar_t * ext = wcsrchr(file,L'.') + 1;
if(!_wcsicmp(ext,L"mp3")) strncpy(codec,"MP3",3);
else if(!_wcsicmp(ext,L"wma")) strncpy(codec,"WMA",3);
if(!item->album) item->album = _wcsdup(L"");
if(!item->artist) item->artist = _wcsdup(L"");
if(!item->title) item->title = _wcsdup(L"");
*size = (long)(2/*count*/+2/*type*/+6/*namelen+datalen*/+strlen(TITLE)+2*wcslen(item->title)
+2+6+strlen(ALBUM)+2*wcslen(item->album)
+2+6+strlen(ARTIST)+2*wcslen(item->artist)
+2+6+strlen(CODEC)+strlen(codec)
+2+6+strlen(FILESIZE)+sizeof(long)
+2+6+strlen(LENGTH)+sizeof(long));
int count = 6;
if (item->year > 0 ){
*size+=2+6+(long)strlen(YEAR)+sizeof(short);
count++;
}
if (item->genre) {
*size+=(long)(2+6+strlen(GENRE)+2*wcslen(item->genre));
count++;
}
if (item->track>0) {
*size+= (long)(2+6+strlen(TRACKNUM)+sizeof(short));
count++;
}
BYTE *buf = (BYTE*)calloc(1,*size);
BYTE *ptr = buf;
memcpy(ptr, &count, sizeof(short));
ptr += sizeof(short);
ptr = setAttrib(ptr,2,TITLE,(BYTE*)((wchar_t*)(item->title)),(int)wcslen(item->title)*2);
ptr = setAttrib(ptr,2,ARTIST,(BYTE*)((wchar_t*)(item->artist)), (int)wcslen(item->artist)*2);
ptr = setAttrib(ptr,2,ALBUM,(BYTE*)((wchar_t*)(item->album)), (int)wcslen(item->album)*2);
if(item->genre) ptr = setAttrib(ptr,2,GENRE,(BYTE*)((wchar_t*)(item->genre)), (int)wcslen(item->genre)*2);
short v = item->track;
if(item->track>0) ptr = setAttrib(ptr,1,TRACKNUM,(BYTE*)&v,2);
v = item->year;
if(item->year>0) ptr = setAttrib(ptr,1,YEAR,(BYTE*)&v,2);
ptr = setAttrib(ptr,0,CODEC,(BYTE*)codec,(int)strlen(codec));
ptr = setAttrib(ptr,1,LENGTH,(BYTE*)&item->length,4);
__int64 filesize = fileSize(file);
ptr = setAttrib(ptr,1,FILESIZE,(BYTE*)&filesize,4);
return buf;
}
BOOL NJBDevice::WindowMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) {
case WM_USER: // start add item
if(transferItem.status == 0) {
long size;
BYTE * buf = makeMetaFromItemRecord(const_cast<itemRecordW *>(transferItem.track),transferItem.file,&size);
HRESULT hr = m_pCTJukebox2->AddItem(id,kAudioTrackType,SysAllocString(transferItem.file),size,(IUnknown*)buf);
transferItem.meta = buf;
if(hr != S_OK) this->WindowMessage(hwnd,WM_DAPSDK_ADDITEM_COMPLETE,-1,0);
}
break;
case WM_DAPSDK_ADDITEM_PROGRESS:
{
wchar_t buf[100] = {0};
wsprintf(buf,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING_PERCENT),(int)wParam);
transferItem.callback(transferItem.callbackContext,buf);
}
break;
case WM_DAPSDK_ADDITEM_COMPLETE:
if(wParam == 0) {
transferItem.callback(transferItem.callbackContext,WASABI_API_LNGSTRINGW(IDS_DONE));
Song * song = new Song;
song->trackid = (int)lParam;
FillSongFromMeta(transferItem.meta,song);
song->track = transferItem.track->track;
song->year = transferItem.track->year;
*transferItem.songid = (songid_t)song;
}
else {
transferItem.callback(transferItem.callbackContext,WASABI_API_LNGSTRINGW(IDS_ERROR));
}
transferItem.status = (wParam==0?1:2);
free(transferItem.meta);
break;
case WM_USER+1: // start get item
if(revTransferItem.status == 0) {
Song * song = (Song*)*revTransferItem.songid;
DAPSDK_ID item = {song->trackid,kAudioTrackType,song->title};
// memory allocated by SysAllocString is freed by COM (why, i don't know)
HRESULT hr = m_pCTJukebox2->GetItem(id,SysAllocString(revTransferItem.file),(IUnknown*)&item);
if(hr != S_OK) WindowMessage(hwnd,WM_DAPSDK_GETITEM_COMPLETE,-1,0);
}
break;
case WM_DAPSDK_GETITEM_PROGRESS:
{
wchar_t buf[100] = {0};
wsprintf(buf,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING_PERCENT),(int)wParam);
revTransferItem.callback(revTransferItem.callbackContext,buf);
}
break;
case WM_DAPSDK_GETITEM_COMPLETE:
revTransferItem.callback(revTransferItem.callbackContext,
WASABI_API_LNGSTRINGW((wParam==0?IDS_DONE:IDS_ERROR)));
revTransferItem.status = (wParam==0?1:2);
break;
}
return 0;
}
//p75
int NJBDevice::transferTrackToDevice(const itemRecordW * track,void * callbackContext,void (*callback)(void * callbackContext, wchar_t * status),songid_t * songid,int * killswitch) {
wchar_t file[2048] = {0};
wcsncpy(file,track->filename,2048);
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;
wcsncpy(file,newfile,2048);
deletefile=true;
}
EnterCriticalSection(&csTransfer);
callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING));
transferItem.file = file;
transferItem.callback = callback;
transferItem.callbackContext = callbackContext;
transferItem.status=0; // in progress
transferItem.killswitch = killswitch;
transferItem.songid = songid;
transferItem.track = track;
//now start the transfer
PostMessage(messageWindow,WM_USER,0,0);
while(transferItem.status==0) Sleep(10); // wait for transfer
// transfer completed
int ret = transferItem.status==1?0:-1;
LeaveCriticalSection(&csTransfer);
if(deletefile) _wunlink(file);
return ret;
}
int NJBDevice::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 = fileSize(track->filename);
else l = (__int64)k;
} else {
wchar_t * ext = wcsrchr(track->filename,L'.');
if(!ext) return -2;
if(_wcsicmp(ext,L".mp3") && _wcsicmp(ext,L".wma") && _wcsicmp(ext,L".wav")) return -2;
l = fileSize(track->filename);
}
if(transferQueueLength + l + 1000000 > getDeviceCapacityAvailable())
return -1;
else {
transferQueueLength += l;
return 0;
}
}
void NJBDevice::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;
}
transferQueueLength -= l;
}
__int64 NJBDevice::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,L'.');
if(!ext) return 0;
if(_wcsicmp(ext,L".mp3") && _wcsicmp(ext,L".wma") && _wcsicmp(ext,L".wav")) return 0;
return fileSize(track->filename);
}
void NJBDevice::deleteTrack(songid_t songid) {
Song * s = (Song*)songid;
for(int i=0; i<playlists.GetSize(); i++) {
Playlist * pl = (Playlist *)playlists.Get(i);
int l = pl->songs.GetSize();
while(l-- > 0) if(pl->songs.Get(l) == (void*)s) { pl->songs.Del(l); if(i>0) pl->dirty=true; }
}
DAPSDK_ID item = {s->trackid,kAudioTrackType,s->title};
m_pCTJukebox2->DeleteItem(id,(IUnknown*)&item);
delete s;
}
void NJBDevice::commitChanges() {
for(int i=1; i<playlists.GetSize(); i++) {
Playlist * pl = (Playlist *)playlists.Get(i);
if(pl->dirty) {
pl->dirty = false;
DAPSDK_ID parentold = {pl->plid,kPlaylistType,pl->name};
m_pCTJukebox2->DeleteParentItem(id,(IUnknown*)&parentold);
DAPSDK_ID parent = {0,kPlaylistType,_wcsdup(pl->name)};
m_pCTJukebox2->AddParentItem(id,(IUnknown*)&playlistRoot,(IUnknown*)&parent);
pl->plid = parent.lID;
long l = pl->songs.GetSize();
DAPSDK_ID * list = (DAPSDK_ID *)calloc(sizeof(DAPSDK_ID),l);
for(int j=0; j<l; j++) {
Song * s = (Song*)pl->songs.Get(j);
if(s) {
list[j].lID = s->trackid;
list[j].lType = kAudioTrackType;
list[j].bstrName = SysAllocString(s->title);
}
}
m_pCTJukebox2->AddItemsToParentItem(id,(IUnknown*)&parent,l,(IUnknown*)list);
free(list);
}
}
}
int NJBDevice::getPlaylistCount() {
return playlists.GetSize();
}
void NJBDevice::getPlaylistName(int playlistnumber, wchar_t * buf, int len) {
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
lstrcpyn(buf,pl->name,len);
}
int NJBDevice::getPlaylistLength(int playlistnumber) {
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
return pl->songs.GetSize();
}
songid_t NJBDevice::getPlaylistTrack(int playlistnumber,int songnum) {
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
return (songid_t) pl->songs.Get(songnum);
}
void NJBDevice::setPlaylistName(int playlistnumber, const wchar_t * buf) {
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
lstrcpyn(pl->name,buf,fieldlen);
DAPSDK_ID item = {pl->plid,kPlaylistType,pl->name};
BSTR name = SysAllocString(buf);
m_pCTJukebox2->RenameParentItem(id,(IUnknown*)&item, name);
SysFreeString(name);
}
void NJBDevice::playlistSwapItems(int playlistnumber, int posA, int posB) {
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
void * a = pl->songs.Get(posA);
void * b = pl->songs.Get(posB);
pl->songs.Set(posA,b);
pl->songs.Set(posB,a);
pl->dirty = true;
}
static int sortby;
#define RETIFNZ(v) if ((v)!=0) return v;
#define STRCMP_NULLOK _wcsicmp
static int sortFunc(const void *elem1, const void *elem2)
{
int use_by = sortby;
Song *a=(Song *)*(void **)elem1;
Song *b=(Song *)*(void **)elem2;
// 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
{
int v=STRCMP_NULLOK(a->title,b->title);
RETIFNZ(v)
use_by=SORTBY_ARTIST;
}
else if (use_by == SORTBY_ARTIST) // artist -> album -> disc -> track -> title
{
int v=STRCMP_NULLOK(a->artist,b->artist);
RETIFNZ(v)
use_by=SORTBY_ALBUM;
}
else if (use_by == SORTBY_ALBUM) // album -> disc -> track -> title -> artist
{
int v=STRCMP_NULLOK(a->album,b->album);
RETIFNZ(v)
use_by=SORTBY_DISCNUM;
}
else if (use_by == SORTBY_TRACKNUM) // track -> title -> artist -> album -> disc
{
int v1=a->track;
int v2=b->track;
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
{
int v=STRCMP_NULLOK(a->genre,b->genre);
RETIFNZ(v)
use_by=SORTBY_ARTIST;
}
else break; // no sort order?
}
return 0;
}
#undef RETIFNZ
#undef STRCMP_NULLOK
void NJBDevice::sortPlaylist(int playlistnumber, int sortBy) {
sortby = sortBy;
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
qsort(pl->songs.GetAll(),pl->songs.GetSize(),sizeof(void*),sortFunc);
pl->dirty=true;
}
void NJBDevice::addTrackToPlaylist(int playlistnumber, songid_t songid) {
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
pl->songs.Add((void*)songid);
pl->dirty = true;
}
void NJBDevice::removeTrackFromPlaylist(int playlistnumber, int songnum) {
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
pl->songs.Del(songnum);
pl->dirty = true;
}
void NJBDevice::deletePlaylist(int playlistnumber) {
Playlist * pl = (Playlist *)playlists.Get(playlistnumber);
DAPSDK_ID parent = {pl->plid,kPlaylistType,pl->name};
m_pCTJukebox2->DeleteParentItem(id,(IUnknown*)&parent);
playlists.Del(playlistnumber);
delete pl;
}
int NJBDevice::newPlaylist(const wchar_t * name) {
Playlist * pl = new Playlist;
pl->dirty = false;
lstrcpyn(pl->name,name,fieldlen);
DAPSDK_ID parent = {0,kPlaylistType,pl->name};
m_pCTJukebox2->AddParentItem(id,(IUnknown*)&playlistRoot,(IUnknown*)&parent);
pl->plid = parent.lID;
playlists.Add(pl);
return playlists.GetSize() - 1;
}
void NJBDevice::getTrackArtist(songid_t songid, wchar_t * buf, int len) {lstrcpyn(buf,((Song*)songid)->artist,len);}
void NJBDevice::getTrackAlbum(songid_t songid, wchar_t * buf, int len) {lstrcpyn(buf,((Song*)songid)->album,len);}
void NJBDevice::getTrackTitle(songid_t songid, wchar_t * buf, int len) {lstrcpyn(buf,((Song*)songid)->title,len);}
void NJBDevice::getTrackGenre(songid_t songid, wchar_t * buf, int len) {lstrcpyn(buf,((Song*)songid)->genre,len);}
int NJBDevice::getTrackTrackNum(songid_t songid) {return ((Song*)songid)->track;}
int NJBDevice::getTrackDiscNum(songid_t songid) {return -1;}
int NJBDevice::getTrackYear(songid_t songid) {return ((Song*)songid)->year;}
__int64 NJBDevice::getTrackSize(songid_t songid) {return ((Song*)songid)->size;}
int NJBDevice::getTrackLength(songid_t songid) {return ((Song*)songid)->length;}
int NJBDevice::getTrackBitrate(songid_t songid) {return -1;}
int NJBDevice::getTrackPlayCount(songid_t songid) {return -1;}
int NJBDevice::getTrackRating(songid_t songid) {return -1;}
__time64_t NJBDevice::getTrackLastPlayed(songid_t songid) {return -1;}
__time64_t NJBDevice::getTrackLastUpdated(songid_t songid) {return -1;}
void NJBDevice::getTrackExtraInfo(songid_t songid, const wchar_t * field, wchar_t * buf, int len) {
if(!wcscmp(field,L"ext")) {
Song * s = (Song *)songid;
lstrcpyn(buf,(wchar_t*)AutoWide(s->codec),len);
wchar_t * p = buf;
while(p && *p) { *p=towlower(*p); p++; }
}
}
void NJBDevice::setTrackArtist(songid_t songid, const wchar_t * value) {
Song * s = (Song *)songid;
lstrcpyn(s->artist,value,fieldlen);
DAPSDK_ID item = {s->trackid,kAudioTrackType,s->title};
m_pCTJukebox2->SetItemAttribute(id,(IUnknown*)&item,L"ARTIST",2,(long)wcslen(value)*2+2,(IUnknown*)value);
}
void NJBDevice::setTrackAlbum(songid_t songid, const wchar_t * value) {
Song * s = (Song *)songid;
lstrcpyn(s->album,value,fieldlen);
DAPSDK_ID item = {s->trackid,kAudioTrackType,s->title};
m_pCTJukebox2->SetItemAttribute(id,(IUnknown*)&item,L"ALBUM",2, (long)wcslen(value)*2+2,(IUnknown*)value);
}
void NJBDevice::setTrackTitle(songid_t songid, const wchar_t * value) {
Song * s = (Song *)songid;
lstrcpyn(s->title,value,fieldlen);
DAPSDK_ID item = {s->trackid,kAudioTrackType,s->title};
m_pCTJukebox2->SetItemAttribute(id,(IUnknown*)&item,L"TITLE",2, (long)wcslen(value)*2+2,(IUnknown*)value);
}
void NJBDevice::setTrackGenre(songid_t songid, const wchar_t * value) {
Song * s = (Song *)songid;
lstrcpyn(s->genre,value,fieldlen);
DAPSDK_ID item = {s->trackid,kAudioTrackType,s->title};
m_pCTJukebox2->SetItemAttribute(id,(IUnknown*)&item,L"GENRE",2, (long)wcslen(value)*2+2,(IUnknown*)value);
}
void NJBDevice::setTrackTrackNum(songid_t songid, int value) {
Song * s = (Song *)songid;
s->track = value;
DAPSDK_ID item = {s->trackid,kAudioTrackType,s->title};
m_pCTJukebox2->SetItemAttribute(id,(IUnknown*)&item,L"TRACK NUM",1,sizeof(short),(IUnknown*)&value);
}
void NJBDevice::setTrackYear(songid_t songid, int value) {
Song * s = (Song *)songid;
s->year = value;
DAPSDK_ID item = {s->trackid,kAudioTrackType,s->title};
m_pCTJukebox2->SetItemAttribute(id,(IUnknown*)&item,L"YEAR",1,sizeof(short),(IUnknown*)&value);
}
int NJBDevice::copyToHardDrive(songid_t s,wchar_t * path,void * callbackContext,void (*callback)(void * callbackContext, wchar_t * status),int * killswitch) {
EnterCriticalSection(&csRevTransfer);
callback(callbackContext,WASABI_API_LNGSTRINGW(IDS_TRANSFERRING));
Song * song = (Song*)s;
wcscat(path,L".");
wcscat(path,AutoWide(song->codec));
wchar_t *p = wcsrchr(path,L'.');
while(p && *p) { *p = towlower(*p); p++; }
revTransferItem.callback = callback;
revTransferItem.callbackContext = callbackContext;
revTransferItem.killswitch = killswitch;
revTransferItem.songid = &s;
revTransferItem.file = path;
revTransferItem.status = 0;
PostMessage(messageWindow,WM_USER+1,0,0);
while(revTransferItem.status==0) Sleep(10); // wait for transfer
int ret = revTransferItem.status==1?0:-1;
LeaveCriticalSection(&csRevTransfer);
return ret;
}
intptr_t NJBDevice::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_ZEN_ICON;
}
break;
case DEVICE_SUPPORTED_METADATA:
return 0x3ef;
}
return 0;
}
+168
View File
@@ -0,0 +1,168 @@
#ifndef _NJBDEVICE_H_
#define _NJBDEVICE_H_
#ifndef _UNICODE
#define _UNICODE
#endif
#ifndef UNICODE
#define UNICODE
#endif
#include <windows.h>
#include <windowsx.h>
#include <Objbase.h>
#include <initguid.h>
#include <stdio.h>
#include <shlobj.h>
#include <wchar.h>
#include "../Plugins/General/gen_ml/ml.h"
#include "../Plugins/Library/ml_pmp/pmp.h"
#include "../Plugins/Library/ml_pmp/transcoder.h"
#include "../Plugins/General/gen_ml/itemlist.h"
#include "Nmsdk.h"
#include "resource.h"
#include "../Agave/Language/api_language.h"
#include <api/service/waServiceFactory.h>
extern PMPDevicePlugin plugin;
extern LRESULT CALLBACK CallbackWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern C_ItemList devices;
extern ICTJukebox2 * m_pCTJukebox2;
#define fieldlen 256
class Playlist {
public:
bool dirty;
int plid;
wchar_t name[fieldlen];
C_ItemList songs;
};
class Song {
public:
char codec[5];
int trackid;
wchar_t artist[fieldlen];
wchar_t album[fieldlen];
wchar_t title[fieldlen];
wchar_t genre[fieldlen];
int year,track,size,length;
};
class TransferItem {
public:
const itemRecordW * track;
void* callbackContext;
void (*callback)(void * callbackContext, wchar_t * status);
songid_t * songid;
int * killswitch;
int status;
BYTE * meta;
wchar_t * file;
};
class NJBDevice : public Device {
public:
Transcoder * transcoder;
BYTE serial[16];
__int64 transferQueueLength;
DAPSDK_ID playlistRoot;
C_ItemList playlists;
int id;
HWND messageWindow;
TransferItem transferItem;
TransferItem revTransferItem;
CRITICAL_SECTION csTransfer;
CRITICAL_SECTION csRevTransfer;
NJBDevice(long id);
virtual ~NJBDevice();
virtual BOOL WindowMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
virtual __int64 getDeviceCapacityAvailable(); // in bytes
virtual __int64 getDeviceCapacityTotal(); // in bytes
virtual void Eject(); // if you ejected successfully, you MUST call plugin.deviceDisconnected(this) and delete this;
virtual void Close(); // save any changes, and call plugin.deviceDisconnected(this) AND delete this;
// return 0 for success, -1 for failed or cancelled
virtual int transferTrackToDevice(const itemRecordW * track, // the track to transfer
void * callbackContext, //pass this to the callback
void (*callback)(void * callbackContext, wchar_t * status), // call this every so often so the GUI can be updated. Including when finished!
songid_t * songid, // fill in the songid when you are finished
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
);
virtual int trackAddedToTransferQueue(const itemRecordW * track); // return 0 to accept, -1 for "not enough space", -2 for "incorrect format"
virtual void trackRemovedFromTransferQueue(const itemRecordW * track);
virtual __int64 getTrackSizeOnDevice(const itemRecordW * track); // return the amount of space taken up on the device by the track, or 0 for incompatable (usually the filesize, unless you are transcoding)
virtual void deleteTrack(songid_t songid); // physically remove from device. Be sure to remove it from all the playlists!
virtual void commitChanges(); // optional. Will be called at a good time to save changes
virtual int getPlaylistCount(); // always at least 1. playlistnumber 0 is the Master Playlist containing all tracks.
// PlaylistName(0) should return the name of the device.
virtual void getPlaylistName(int playlistnumber, wchar_t * buf, int len);
virtual int getPlaylistLength(int playlistnumber);
virtual songid_t getPlaylistTrack(int playlistnumber,int songnum); // returns a songid
virtual void setPlaylistName(int playlistnumber, const wchar_t * buf); // with playlistnumber={}, set the name of the device.
virtual void playlistSwapItems(int playlistnumber, int posA, int posB); // swap the songs at position posA and posB
virtual void sortPlaylist(int playlistnumber, int sortBy); // only implement if you are a non-cached device!!!
virtual void addTrackToPlaylist(int playlistnumber, songid_t songid); // adds songid to the end of the playlist
virtual void removeTrackFromPlaylist(int playlistnumber, int songnum); //where songnum is the position of the track in the playlist
virtual void deletePlaylist(int playlistnumber);
virtual int newPlaylist(const wchar_t * name); // create empty playlist, returns playlistnumber
virtual void getTrackArtist(songid_t songid, wchar_t * buf, int len);
virtual void getTrackAlbum(songid_t songid, wchar_t * buf, int len);
virtual void getTrackTitle(songid_t songid, wchar_t * buf, int len);
virtual int getTrackTrackNum(songid_t songid);
virtual int getTrackDiscNum(songid_t songid);
virtual void getTrackGenre(songid_t songid, wchar_t * buf, int len);
virtual int getTrackYear(songid_t songid);
virtual __int64 getTrackSize(songid_t songid); // in bytes
virtual int getTrackLength(songid_t songid); // in millisecs
virtual int getTrackBitrate(songid_t songid); // in kbps
virtual int getTrackPlayCount(songid_t songid);
virtual int getTrackRating(songid_t songid); //0-5
virtual __time64_t getTrackLastPlayed(songid_t songid); // in unix time format
virtual __time64_t getTrackLastUpdated(songid_t songid); // in unix time format
virtual void getTrackExtraInfo(songid_t songid, const wchar_t * field, wchar_t * buf, int len); //optional
// feel free to ignore any you don't support
virtual void setTrackArtist(songid_t songid, const wchar_t * value);
virtual void setTrackAlbum(songid_t songid, const wchar_t * value);
virtual void setTrackTitle(songid_t songid, const wchar_t * value);
virtual void setTrackTrackNum(songid_t songid, int value);
virtual void setTrackDiscNum(songid_t songid, int value){};
virtual void setTrackGenre(songid_t songid, const wchar_t * value);
virtual void setTrackYear(songid_t songid, int year);
virtual void setTrackPlayCount(songid_t songid, int value){};
virtual void setTrackRating(songid_t songid, int value){};
virtual void setTrackLastPlayed(songid_t songid, __time64_t value){}; // in unix time format
virtual void setTrackLastUpdated(songid_t songid, __time64_t value){}; // in unix time format
virtual void setTrackExtraInfo(songid_t songid, const wchar_t * field, const wchar_t * value) {}; //optional
virtual bool playTracks(songid_t * songidList, int listLength, int startPlaybackAt, bool enqueue){return false;}; // return false if unsupported
virtual intptr_t extraActions(intptr_t param1, intptr_t param2, intptr_t param3,intptr_t param4);
virtual bool copyToHardDriveSupported() {return true;} // for now...
virtual __int64 songSizeOnHardDrive(songid_t song) {return getTrackSize(song);} // how big a song will be when copied back. Return -1 for not supported.
virtual int copyToHardDrive(songid_t song, // the song to copy
wchar_t * path, // path to copy to, in the form "c:\directory\song". The directory will already be created, you must append ".mp3" or whatever to this string! (there is space for at least 10 new characters).
void * callbackContext, //pass this to the callback
void (*callback)(void * callbackContext, wchar_t * status), // call this every so often so the GUI can be updated. Including when finished!
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
); // -1 for failed/not supported. 0 for success.
};
#endif //_NJBDEVICE_H_
+922
View File
@@ -0,0 +1,922 @@
/////////////////////////////////////////////////////////////////////////////////////
//
// File: nmsdk.h
//
// Purpose: Combination of the Jukebox SDK2 header file and the NomadII SDK2 header file.
//
// Notes: Please make sure to include the COM Stuffs <Objbase.h> and <initguid.h>
// at the beginning of the application programs. Otherwise, it will get Link Errors.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Creative Technology Ltd., 2001. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// nmsdk.h : main header file for export
// Version: 1.0.7.0
/////////////////////////////////////////////////////////////////////////////
#ifndef __nmsdk_h__
#define __nmsdk_h__
//
// COM Interface Declaration
//
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
//////////////////////////////////////////////////////////////////////////
// Class ID //
//////////////////////////////////////////////////////////////////////////
//CLSID CLSID_CTJukeBox2:
// {BD1A6357-3E9B-4f1b-8375-AEE989ED6C5E}
DEFINE_GUID(CLSID_CTJukeBox2,
0xbd1a6357, 0x3e9b, 0x4f1b, 0x83, 0x75, 0xae, 0xe9, 0x89, 0xed, 0x6c, 0x5e);
//CLSID CLSID_CTNOMAD2:
// {0EBE3156-FD3A-4f5c-ABDB-71E3BEEAD091}
DEFINE_GUID(CLSID_CTNOMAD2,
0xebe3156, 0xfd3a, 0x4f5c, 0xab, 0xdb, 0x71, 0xe3, 0xbe, 0xea, 0xd0, 0x91);
//////////////////////////////////////////////////////////////////////////
// return codes //
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// JukeBox & NomadII shared stuffs //
//////////////////////////////////////////////////////
// Additional Error codes
#define DAPSDK_SUCCESS 0x00
// General Error
#define DAPSDK_FAILED 0x01
#define DAPSDK_E_DEVICE_BUSY 0x02
#define DAPSDK_E_STORAGE_FULL 0x03
#define DAPSDK_E_SETTIME_REJECTED 0x05
#define DAPSDK_E_ITEM_SIZE_MISSING 0x14 //NMJB_E_TRACK_SIZE_MISSING
#define DAPSDK_E_ITEM_UPLOAD_DENIED 0x18 //NMJB_E_TRACK_UPLOAD_DENIED
#define DAPSDK_E_PLAYER_NOT_CONNECTED 0x80
#define DAPSDK_E_CANCELLED 0x81
#define DAPSDK_E_PORT_UNAVAILABLE 0x82
#define DAPSDK_E_OUT_OF_MEMORY 0x83
#define DAPSDK_E_FILEOPEN_ERR 0x84
#define DAPSDK_E_ITEM_NOT_FOUND 0x85
#define DAPSDK_E_LOAD_COMPONENTS_FAILED 0x86
#define DAPSDK_E_ID_INVALID 0x87
#define DAPSDK_E_FILETYPE_ILLEGAL 0x88
#define DAPSDK_E_LOADRES_FAIL 0x89
#define DAPSDK_E_FORMAT_NOT_FOUND 0x8a
#define DAPSDK_E_FILE_ALREADY_EXISTS 0x8b
#define DAPSDK_E_LIB_CORRUPTED 0x8c
#define DAPSDK_E_LIB_BUSY 0x8d
#define DAPSDK_E_FILE_READ_WRITE_FAILED 0x8e //NMJB_E_FILE_WRITE_FAILED
#define DAPSDK_E_INVALID_FILEPATH 0x8f
#define DAPSDK_E_UNSUPPORTED 0x91
#define DAPSDK_E_NORIGHTS 0x95
#define DAPSDK_E_UNDEFINED_ERR 0xff
//////////////////////////////////////////////////////
// NomadII stuffs //
//////////////////////////////////////////////////////
#define DAPSDK_E_SMARTMEDIA_WRITE_PROTECTED 0x98
#define DAPSDK_E_NO_STORAGE 0x99 //No internal media or smart media
//////////////////////////////////////////////////////
// JukeBox stuffs //
//////////////////////////////////////////////////////
// General Error
#define DAPSDK_E_HD_GENERAL_ERROR 0x04
// Track Management Error
#define DAPSDK_E_TRACK_NOT_FOUND 0x10
#define DAPSDK_E_TRACK_ALREADY_EXIST 0x11
#define DAPSDK_E_TRACK_TITLE_MISSING 0x12
#define DAPSDK_E_TRACK_CODEC_MISSING 0x13
#define DAPSDK_E_TRACK_IO_OPERATION_ABORTED 0x15
#define DAPSDK_E_TRACK_READ_WRITE_ERROR 0x16
#define DAPSDK_E_TRACK_NOT_OPENED 0x17
// Playlist Error
#define DAPSDK_E_PL_NOT_FOUND 0x20
#define DAPSDK_E_PL_ALREADY_EXIST 0x21
#define DAPSDK_E_PL_ITEM_NOT_FOUND 0x22
#define DAPSDK_E_PL_ITEM_ALREADY_EXIST 0x23
//Additional
#define DAPSDK_E_DISKFULL_FOR_DOWNLOAD 0x90
#define DAPSDK_E_STATUS_TIMEOUT 0x06
// Transport Control Error
#define DAPSDK_E_END_OF_TRACK 0x30
#define DAPSDK_E_END_OF_LIST 0x31
#define DAPSDK_E_CODEC_NOT_SUPPORTED 0x32
#define DAPSDK_E_DATA_CORRUPTED 0x33
#define DAPSDK_E_SAMPLING_RATE_NOT_SUPPORTED 0x34
#define DAPSDK_E_DECODING_ERROR 0x35
#define DAPSDK_E_POSITION_OUTOF_RANGE 0x36
#define DAPSDK_E_NOT_STOPPED 0x37
// Audio Control Error
#define DAPSDK_E_UNKNOW_PROPERTY 0x40
#define DAPSDK_E_VALUE_OUTOF_RANGE 0x41
// USB Transaction Error
#define DAPSDK_E_DATA_FILE_NOT_FOUND 0x60
#define DAPSDK_E_DATA_FILE_TOO_BIG 0x61
#define DAPSDK_E_DATA_FILE_ALREADY_EXIST 0x62
#define DAPSDK_E_TOO_MANY_DATA_FILES 0x63
//additional
#define DAPSDK_E_WMDM_INIT_FAILED 0x92
#define DAPSDK_E_INVALID_ARGUMENT 0x93
#define DAPSDK_E_PARENTNODE_NOT_EXIST 0x94
#define DAPSDK_E_NORIGHTS 0x95
#define DAPSDK_E_PATH_EXCESS_LEN 0x96
#define DAPSDK_E_LOAD_PROC_FAILED 0x97
// New Error code for MultiApplication assess of Nomad Jukebox 2/3/Zen
#define DAPSDK_E_PMSMAN_CREATEDIRECTORY_FAILED 0x0100
#define DAPSDK_E_DEVICE_WRITE_FAILED 0x0200
#define DAPSDK_E_DEVICE_READ_FAILED 0x0300
#define DAPSDK_E_DB_INVALID_REQUEST_ID 0x0400
#define DAPSDK_E_DB_INVALID_NODE_ID 0x0500
#define DAPSDK_E_DWNTHRD_CREATEMETADATA_FAILED 0x0600
#define DAPSDK_E_DEVINFO_INVALID_INDEX 0x0700
#define DAPSDK_E_INVALID_DEVICESETTINGTYPE 0x0800
#define DAPSDK_E_FILESIZE_TOO_BIG 0x0900
#define DAPSDK_E_AUDIOFILE_FORMAT 0x0A00
#define DAPSDK_E_AUDIOFILE_INVALID 0x0B00
#define DAPSDK_E_ACCESS_DENIED 0x0C00
#define DAPSDK_E_FILE_NOT_FOUND 0x0D00
#define DAPSDK_E_EOF 0x0E00
#define DAPSDK_E_COOKIE 0x0F00
#define DAPSDK_E_PLAYBACK_INPROGRESS 0x1000
#define DAPSDK_E_TRANSFER_INPROGRESS 0x1100
#define DAPSDK_E_BUFFER_NOT_ENOUGH 0x1200
// New Error code for Data Folder of Nomad Jukebox 2/3/Zen
#define DAPSDK_E_NOT_A_FOLDER 0x1400 // the target file is not a folder
#define DAPSDK_E_FOLDER_NOT_EMPTY 0x1600 // the target folder is not empty
#define DAPSDK_E_FOLDER_EXIST 0x1700 // the target folder exist
#define DAPSDK_E_FOLDER_NOTEXIST 0x1800 // the target folder does not exist
#define DAPSDK_E_PARENTFOLDER_NOTEXIST 0x1900 // the target parent folder does not exist
#define DAPSDK_E_FILEPATH_TOOLONG 0x1A00 // the target file path is too long
#define DAPSDK_E_FILENAME_TOOLONG 0x1B00 // the target file name is too long
#define DAPSDK_E_INVALID_OPERATION 0x1E00 // the operation cannot be perform
//////////////////////////////////////////////////////////////////////////
// Definitions for WM Messages //
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// JukeBox & NomadII shared stuffs //
//////////////////////////////////////////////////////
// Download message
#define WM_DAPSDK_DOWNLOAD_PROGRESS WM_USER+500
#define WM_DAPSDK_DOWNLOAD_COMPLETE WM_USER+501
// Upload message
#define WM_DAPSDK_GETITEM_PROGRESS WM_USER+502
#define WM_DAPSDK_GETITEM_COMPLETE WM_USER+503
//////////////////////////////////////////////////////
// JukeBox stuffs //
//////////////////////////////////////////////////////
// Device change message
#define WM_DAPSDK_JUKEBOX_REMOVAL WM_USER+508
#define WM_DAPSDK_JUKEBOX_ARRIVAL WM_USER+509
// Playback message
#define WM_DAPSDK_PLAYBACK_COMPLETE WM_USER+504
#define WM_DAPSDK_PLAYLIST_COMPLETE WM_USER+505
#define WM_DAPSDK_PLAYBACK_ERROR WM_USER+506
#define WM_DAPSDK_PLAYBACK_PROGRESS WM_USER+507
// New callback messages for MultiApplication assess of Hotcake
// Notification Messages for database change
#define WM_DAPSDK_CHANGE_BASE WM_USER + 200
#define WM_DAPSDK_MUSIC_ADD_FILE WM_DAPSDK_CHANGE_BASE + 0 // wParam = NodeId added, lParam = nil
#define WM_DAPSDK_MUSIC_DEL_FILE WM_DAPSDK_CHANGE_BASE + 1 // wParam = NodeId deleted, lParam = nil
#define WM_DAPSDK_MUSIC_SETATTR_FILE WM_DAPSDK_CHANGE_BASE + 2 // wParam = NodeId edited, lParam = nil
#define WM_DAPSDK_DATA_ADD_FILE WM_DAPSDK_CHANGE_BASE + 3 // wParam = NodeId added, lParam = nil
#define WM_DAPSDK_DATA_DEL_FILE WM_DAPSDK_CHANGE_BASE + 4 // wParam = NodeId deleted, lParam = nil
#define WM_DAPSDK_DATA_SETATTR_FILE WM_DAPSDK_CHANGE_BASE + 5 // wParam = NodeId edited, lParam = nil
#define WM_DAPSDK_PLAYLIST_ADD_FILE WM_DAPSDK_CHANGE_BASE + 6 // wParam = NodeId added, lParam = nil
#define WM_DAPSDK_PLAYLIST_DEL_FILE WM_DAPSDK_CHANGE_BASE + 7 // wParam = NodeId deleted, lParam = nil
#define WM_DAPSDK_PLAYLIST_SETATTR_FILE WM_DAPSDK_CHANGE_BASE + 8 // wParam = NodeId edited, lParam = nil
#define WM_DAPSDK_PLAYLIST_ITEM_CHANGE WM_DAPSDK_CHANGE_BASE + 9 // wParam = PlaylistNodeId affected, lParam = nil
#define WM_DAPSDK_STORAGEINFO_CHANGE WM_DAPSDK_CHANGE_BASE + 10 // wParam = deviceIndex that change occurred, lParam = nil
#define WM_DAPSDK_ADDITEM_PROGRESS WM_USER+500
#define WM_DAPSDK_ADDITEM_COMPLETE WM_USER+501
/////////////////////////////////////////////////////////////////////////
// struct defines //
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// JukeBox & NomadII shared stuffs //
//////////////////////////////////////////////////////
typedef struct _DAPSDK_DATE_TIME
{
short Year, Month, Day, DayOfWeek;
short Hour, Min, Sec, MilliSec;
} DATE_TIME, *PDATE_TIME;
typedef struct _DAPSDK_FORMAT_INFO
{
long lCodecID;
UCHAR szCodecName[128];
long lSamplingRate;
long lNumChannel;
} FORMAT_INFO, *PFORMAT_INFO;
//-- SDK and firmware version info structure --//
//
// used in GetSDKVersion()
// used in GetDeviceProperties( kFirmwareVersion, kHardwareVersion)
typedef struct _DAPSDK_VERSION
{
WORD major;
WORD minor;
WORD build;
WORD specialBuild;
} DAPSDK_VERSION, *PDAPSDK_VERSION;
//-- Memory Storage Information Structure --//
typedef struct _DAPSDK_STORAGE_INFO
{
ULONG totalH;
ULONG totalL;
ULONG freeH;
ULONG freeL;
} DAPSDK_STORAGE_INFO, *PDAPSDK_STORAGE_INFO;
//-- Identification structure --//
// same for RootItem, ParentItem and Item now //
typedef struct _DAPSDK_ID
{
long lID; // stores the unique ID
long lType; // stores the type (see enum above)
BSTR bstrName; // stores the name
} DAPSDK_ID, *PDAPSDK_ID;
//////////////////////////////////////////////////////
// NomadII stuffs //
//////////////////////////////////////////////////////
typedef struct _DAPSDK_RADIOPRESET
{
DWORD dwPresetIndex;
DWORD dwPresetValue;
} RADIOPRESET, *PRADIOPRESET;
// device info struct
typedef struct _DAPSDK_DEVICE_INFO
{
BYTE cDeviceId[16]; // player's ID
long dwFirmwareVersion; // player's firmware version
long dwHardwareVersion; // player's hardware version
char cDeviceName[32]; // player's name w/o NULL terminator
BYTE byPowerSource; // player's power source status in percent
} DAPSDK_DEVICE_INFO, *PDAPSDK_DEVICE_INFO;
enum
{
kASCII = 0,
kBINARY,
kUNICODE,
};
//////////////////////////////////////////////////////
// Item type for Jukebox (used by lRootItemType, //
// lParentItemType, lItemType parameter) //
//////////////////////////////////////////////////////
enum
{
kAudioTrackType = 1, // this is a audio track
kPlaylistType, // this is a track in the playlist
kDataFileType, // this is a data file
kDataFolderType, // this is a data file folder
};
/////////////////////////////////////////////////////////
// Item type for NomadII (used in lItemType parameter) //
/////////////////////////////////////////////////////////
enum
{
kInternalMemType = 0, // this item resides in internal memory
kExternalMemType, // this item resides in external (removeable) media
};
// Device Property Type Constant
//-- Device Property type (used by lDevicePropertyType parameter in --//
// GetDeviceProperties/SetDeviceProperties --//
enum
{
//////////////////////////////////////////////////////
// JukeBox & NomadII shared stuffs //
//////////////////////////////////////////////////////
kDeviceSerialNumberValue = 1, // GET, <NOMAD II>given the Item type
// in "lpValue" parameter, the return value
// is a pointer to the serial number
// of the specified media.
kFirmwareVersion, // GET, return value is a pointer to
// DAPSDK_VERSION structure indicating the
// current firmware version in the device.
kDeviceNameString, // GET, return value is a pointer to
// BSTR string.
kPowerSourceValue,
kStorageInfoStruct, // GET, return value is a pointer to
// DAPSDK_STORAGE_INFO structure indicating
// the current memory usage.
kDateTimeStruct, // GET/SET, return/set value is a pointer to
// DATE_TIME structure (defined in SDK 1.0)
kOwnerNameString, // GET/SET, return/set value is a pointer to BSTR
// string.
kAudioFormatCount, // GET, return value is a pointer to the number of
// audio format supported by device.
kAudioFormatInfoStruct, // GET, given the index value in "lpValue"
// parameter, the return value is a pointer to
// FORMATINFO structure (defined in SDK 1.0).
kLangEncodeSupport, // GET, returns unsigned long value
// 0x01 == Latin 1(CP1252), 0x80000000 == UNICODE
//////////////////////////////////////////////////////
// JukeBox stuffs //
//////////////////////////////////////////////////////
kHardwareVersion, // GET, return value is a pointer to
// DAPSDK_VERSION structure indicating the
// current hardware version in the device.
kAudioVolumeValue, // GET/SET, return/set value is the pointer to the
// volume level in percentage.
kAudioMuteValue, // GET/SET, return/set value is the pointer to the
// Mute status (1=on, 0=off).
// Treble level in percentage.
kEAXCount, // GET, return value is the pointer to the number
// of EAX settings.
kEAXNameString, // GET, given the index value in "lpValue"
// parameter, the return value is a pointer to
// a BSTR string.
kEAXAmountValue, // GET/SET, given the index value in "lpValue"
// parameter, the return value is the effect
// amount in percentage.
kEAXCurrentIndex, // GET/SET, the value in "lpValue" is used to set
// or retrieve the current EAX selection.
kAudioEQPresetCount, // GET, return value is the pointer to the number
// of EQ settings.
kAudioEQNameString, // GET, given the index value in "lpValue"
// parameter, the return value is a pointer to
// a BSTR string.
kAudioEQAmountValue, // GET/SET, return/set value is the pointer to the
// EQ amount in percentage.
kAudioEQCurrentIndex, // GET/SET, the value in "lpValue" is used to set
// or retrieve the current EQ selection.
//////////////////////////////////////////////////////
// NomadII stuffs //
//////////////////////////////////////////////////////
kFMRadioPresetCount, // GET, returns pointer to number of FM radio
// presets available in the player.
kFMRadioPresetValue, // GET/SET, given the preset index value,
// returns an existing value or sets a new
// preset FM preset. Value in kHz.
kFormatStorage // SET, Do format storage.
};
//Note that all index value is zero-based. Client should call the "kxxxxxxCount" property first before trying to get the value for individual settings in list-type of properties, i.e. kEAXNameString, kAudioFormatInfoStruct...
//Not all properties are readable and writable, some are read-only attributes. Those properties that are read-only are marked with the "GET" strings and those that are read and writable are marked as "GET/SET". Client should not call SetDeviceProperties() with the read-only property type, such call would fail.
//New Property types maybe supported in future by simply adding into the enum list, and publish to developers.
//////////////////////////////////////////////////////
// JukeBox stuffs //
//////////////////////////////////////////////////////
//-- Playback operation type (used by lPlayOperationType parameter in --//
//-- PlayControl() & QueueControl()) --//
enum
{
kPlayTrack = 1, // lpValue stores the pointer to the
// DAPSDK_ITEM_ID structure.
kStopTrack, // lpValue is not used, stop current track, no op
// if no track is currently playing.
kPauseTrack, // lpValue is not used, pause current track, no op
// if no track is currently playing.
kSetPlaybackPosition, // lpValue stores the pointer to the new playback
// position.
kQueueTrack, // lpValue stores the pointer to the
// DAPSDK_ITEM_ID structure.
kClearQueue, // lpValue is not used, clear existing queue.
};
#define TITLE "TITLE"
#define FILESIZE "FILE SIZE"
#define CODEC "CODEC"
#define ALBUM "ALBUM"
#define ARTIST "ARTIST"
#define GENRE "GENRE"
#define LENGTH "LENGTH"
#define TRACKNUM "TRACK NUM"
#define YEAR "YEAR"
#define PLAYONLY "PLAYONLY"
#define TRACKID "TRACK ID"
// new attribute for datafile and datafolder
#define MOD_FILETIME "MODIFIED FILETIME"
#define FILE_ATTRIB "FILE ATTRIB"
#define PARENT_FOLDER "PARENT FOLDER"
#define FOLDERNAME "FOLDER NAME" // data folder name for Nomad Jukebox
#define MULTI_ATTRIB "MULTI ATTRIB" // this is for user to change multiple file attribute at one time.
#define FILENAME "FILE NAME" // file name for Nomad II, data file name for Nomad Jukebox
#define ALLTRACKSKEY -1
//////////////////////////////////////////////////////
// NomadII stuffs //
//////////////////////////////////////////////////////
#define DOS_FILEATTRIB "DOS_FILEATTRIB"
#define DOS_DATETIME "DOS_DATETIME"
//////////////////////////////////////////////////////////////////////////
// ICTJukebox (Interface 1) Methods //
//////////////////////////////////////////////////////////////////////////
// {DFC9207F-4B64-11D4-A4ED-00A0C98E46CC}
DEFINE_GUID(IID_ICTJukebox,
0xdfc9207f, 0x4b64, 0x11d4, 0xa4, 0xed, 0x00, 0xa0, 0xc9, 0x8e, 0x46, 0xcc);
interface ICTJukebox : public IUnknown
{
virtual HRESULT STDMETHODCALLTYPE CancelTransfer(
/*[in]*/long lDeviceID) = 0;
virtual HRESULT STDMETHODCALLTYPE RenamePlaylist(
/*[in]*/long lDeviceID,
/*[in]*/long lPlaylistID,
/*[in]*/BSTR bstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE RemoveTracksFromPlaylist(
/*[in]*/long lDeviceID,
/*[in]*/long lTrackCount,
/*[in]*/long* lpTrackList,
/*[in]*/long lPlaylist) = 0;
virtual HRESULT STDMETHODCALLTYPE AddTracksToPlaylist(
/*[in]*/long lDeviceID,
/*[in]*/long lTrackCount,
/*[in]*/long* lpTrackList,
/*[in]*/long lPlaylist) = 0;
virtual HRESULT STDMETHODCALLTYPE InsertPlaylist(
/*[in]*/long lDeviceID,
/*[in]*/BSTR bstrPlaylistName,
/*[out]*/long* lpPlaylistID) = 0;
virtual HRESULT STDMETHODCALLTYPE DeletePlaylist(
/*[in]*/long lDeviceID,
/*[in]*/long lPlaylistID) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextTrackInPlaylist(
/*[in]*/long lDeviceID,
/*[in]*/long lPlaylistID,
/*[out]*/long* lpTrackID,
/*[out]*/BSTR* lpbstrTrackName) = 0;
virtual HRESULT STDMETHODCALLTYPE FindFirstTrackInPlaylist(
/*[in]*/long lDeviceID,
/*[in]*/long lPlaylistID,
/*[out]*/long* lpTrackID,
/*[out]*/BSTR* lpbstrTrackName) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextPlaylist(
/*[in]*/long lDeviceID,
/*[out]*/long* lpPlaylistID,
/*[out]*/BSTR* lpbstrPlaylistName) = 0;
virtual HRESULT STDMETHODCALLTYPE FindFirstPlaylist(
/*[in]*/long lDeviceID,
/*[out]*/long* lpPlaylistID,
/*[out]*/BSTR* lpbstrPlaylistName) = 0;
virtual HRESULT STDMETHODCALLTYPE ChangeTrackInfo(
/*[in]*/long lDeviceID,
/*[in]*/long lTarckID,
/*[in]*/long lSize,
/*[in]*/IUnknown* lpTrackInfo) = 0;
virtual HRESULT STDMETHODCALLTYPE DeleteTrack(
/*[in]*/long lDeviceID,
/*[in]*/long lTrackID) = 0;
virtual HRESULT STDMETHODCALLTYPE InsertTrack(
/*[in]*/long lDeviceID,
/*[in]*/BSTR bstrFilePath,
/*[in]*/long lSize,
/*[in]*/IUnknown* lpTrackInfo,
/*[out]*/long* lpTrackID) = 0;
virtual HRESULT STDMETHODCALLTYPE GetTrackInfo(
/*[in]*/long lDeviceID,
/*[in]*/long lTrackID,
/*[in]*/long lInSize,
/*[out]*/long* lpOutSize,
/*[out]*/IUnknown* lpTrackInfo) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextTrack(
/*[in]*/long lDeviceID,
/*[in]*/long lKeyID,
/*[out]*/long* lpTrackID,
/*[out]*/BSTR* lpbstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE FindFirstTrack(
/*[in]*/long lDeviceID,
/*[in]*/long lKeyID,
/*[out]*/long* lpTrackID,
/*[out]*/BSTR* lpbstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextKey(
/*[in]*/long lDeviceID,
/*[in]*/long lRootKeyID,
/*[out]*/long* lpKeyID,
/*[out]*/BSTR* lpbstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE FindFirstKey(
/*[in]*/long lDeviceID,
/*[in]*/long lRootKeyID,
/*[out]*/long* lpKeyID,
/*[out]*/BSTR* lpbstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextRootKey(
/*[in]*/long lDeviceID,
/*[out]*/long* lpRootKeyID,
/*[out]*/BSTR* lpbstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE FindFirstRootKey(
/*[in]*/long lDeviceID,
/*[out]*/long* lpRootKeyID,
/*[out]*/BSTR* lpbstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE SetOwnerName(
/*[in]*/long lDeviceID,
/*[in]*/BSTR bstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE GetOwnerName(
/*[in]*/long lDeviceID,
/*[out]*/BSTR* lpbstrName) = 0;
virtual HRESULT STDMETHODCALLTYPE SetDateTime(
/*[in]*/long lDeviceID,
/*[out]*/IUnknown* lpDateTime) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDateTime(
/*[in]*/long lDeviceID,
/*[out]*/IUnknown* lpDateTime) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextFormatSupport(
/*[in]*/long lDeviceID,
/*[out]*/IUnknown* lpFormatInfo) = 0;
virtual HRESULT STDMETHODCALLTYPE FindFirstFormatSupport(
/*[in]*/long lDeviceID,
/*[out]*/IUnknown* lpFormatInfo) = 0;
virtual HRESULT STDMETHODCALLTYPE GetStorageInfo(
/*[in]*/long lDeviceID,
/*[out]*/unsigned long* lpTotalMemHigh,
/*[out]*/unsigned long* lpTotalMemLow,
/*[out]*/unsigned long* lpFreeMemHigh,
/*[out]*/unsigned long* lpFreeMemLow ) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDeviceInfo(
/*[in]*/long lDeviceID,
/*[out]*/IUnknown* lpDeviceInfo) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDeviceCount(
/*[out]*/long* lpDeviceCount) = 0;
virtual HRESULT STDMETHODCALLTYPE SetCallbackWindow(
/*[in]*/long lDeviceID,
/*[in]*/long hWnd) = 0;
virtual HRESULT STDMETHODCALLTYPE GetSDKVersion(
/*[out]*/long* lpVersion) = 0;
virtual HRESULT STDMETHODCALLTYPE ShutDown() = 0;
virtual HRESULT STDMETHODCALLTYPE Initialize() = 0;
};
//////////////////////////////////////////////////////////////////////////
// ICTJukebox2 (Interface 2) Methods //
//////////////////////////////////////////////////////////////////////////
DEFINE_GUID(IID_ICTJukebox2,
0xdfc92080, 0x4b64, 0x11d4, 0xa4, 0xed, 0x00, 0xa0, 0xc9, 0x8e, 0x46, 0xcc);
interface ICTJukebox2 : public IUnknown
{
virtual HRESULT STDMETHODCALLTYPE Initialize2() = 0;
virtual HRESULT STDMETHODCALLTYPE ShutDown2() = 0;
virtual HRESULT STDMETHODCALLTYPE SetCallbackWindow2(
long lDeviceID,
long hWnd ) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDeviceCount2(
long* lpDeviceCount ) = 0;
//-- Canceling I/O --//
virtual HRESULT STDMETHODCALLTYPE CancelTransfer2(
long lDeviceID ) = 0;
//-- GetSDKVersion2() Fucntion Descriptions --//
// This function overides the same function in interface 1, this is to
// return a more meaningful version information to the client which is
// clearly specified in the DAPSDK_VERSION structure
virtual HRESULT STDMETHODCALLTYPE GetSDKVersion2(
IUnknown* lpSDKVersion ) = 0;
//_______________________ Querying RootItem __________________________//
virtual HRESULT STDMETHODCALLTYPE FindFirstRootItem (
long lDeviceID,
IUnknown* lpRootItemID ) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextRootItem (
long lDeviceID,
IUnknown* lpRootItemID ) = 0;
//______________________ Querying ParentItem __________________________//
virtual HRESULT STDMETHODCALLTYPE FindFirstParentItem (
long lDeviceID,
IUnknown* lRootItemID,
IUnknown* lpParentItemID ) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextParentItem (
long lDeviceID,
IUnknown* lRootItemID,
IUnknown* lpParentItemID ) = 0;
//______________________ ParentItem Management __________________________ //
//-- AddParentItem() Fucntion Descriptions --//
// Client can only add Parent Item of the same type as the RootItem. For
// example, client cannot add a kDataFileType Parent item into a RootItem
// type of kAudioTrackType.
//
// As of current firmware implementation, client can only add ParentItem
// into a RootItem that has a type of kPlaylistType. Adding ParentItem into
// other RootItem type will fail.
virtual HRESULT STDMETHODCALLTYPE AddParentItem (
long lDeviceID,
IUnknown* lRootItemID,
IUnknown* lParentItemID ) = 0;
//-- DeleteParentItem() Function Description --//
// Client can only delete ParentItem of type kPlaylistType. Deleting other
// ParentItem type will fail.
virtual HRESULT STDMETHODCALLTYPE DeleteParentItem (
long lDeviceID,
IUnknown* lParentItemID ) = 0;
//-- RenameParentItem() Function Description --//
// Client can only rename ParentItem of type kPlaylistType. Renaming other
// ParentItem type will fail.
//
// The updated DAPSDK_PARENTITEM_ID structure is returned in lParentItemID
// parameter.
virtual HRESULT STDMETHODCALLTYPE RenameParentItem (
long lDeviceID,
IUnknown* lParentItemID,
BSTR bstrNewParentItemName ) = 0;
//__________________________ Querying Item ______________________________//
virtual HRESULT STDMETHODCALLTYPE FindFirstItem (
long lDeviceID,
IUnknown* lParentItemID,
IUnknown* lpItemID ) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextItem (
long lDeviceID,
IUnknown* lParentItemID,
IUnknown* lpItemID ) = 0;
//_____________________ Getting Item Attributes __________________________//
//-- GetItemAttribute() Function Description --//
// This function returns the TrackInfo data for all Item type. But for
// kDataFileType and kPlaylistFileType, the TrackInfo data contain only
// file name, file type and file size. In contrast, the item attribute
// for a kAudioTrackType may contain all information similar to the ID3tag
// information that a typical MP3 file has.
virtual HRESULT STDMETHODCALLTYPE GetItemAttribute (
long lDeviceID,
IUnknown* lpItemID,
long lInItemInfoSize,
long* lOutItemInfoSize,
IUnknown* lpItemInfo ) = 0;
//-- SetItemAttribute() Function Description --//
// This function allows client to set TrackInfo attributes of a
// kAudioTrackItem only. Setting other item type will fail.
//
// It allows client to set a particular attribute data according to the name
// and type given in the parameters. Note that only one attribute can be set
// at a time.
virtual HRESULT STDMETHODCALLTYPE SetItemAttribute (
long lDeviceID,
IUnknown* lpItemID,
BSTR bstrAttributeName,
long lAttributeType,
long lAttributeDataSize,
IUnknown* lpAttributeData ) = 0;
//____________________________ Item Management ___________________________//
//-- AddItem() Function Description --//
// This function initiates the file download from the computer to the
// device. Client should call this function to download audio tracks
// like MP3, WMA and WAVE and data files. Client are not allow
// to download an item of kPlaylistType, use AddItemsToParentItem to add
// item of type kPlaylistType.
virtual HRESULT STDMETHODCALLTYPE AddItem (
long lDeviceID,
long lItemType,
BSTR bstrSrcFileName,
long lItemInfoSize,
IUnknown* lpItemInfo) = 0;
//-- AddItemsToParentItem() Function Description --//
// Client call this function to add kAudioTrackType item into the ParentItem
// of type kPlaylistType. Only kAudioTrackType items are accepted, and only
// ParentItem of type kPlaylistType can accept such addition.
virtual HRESULT STDMETHODCALLTYPE AddItemsToParentItem(
long lDeviceID,
IUnknown* lpParentItemID,
long lItemIDCount,
IUnknown* lpItemIDList ) = 0;
//-- DeleteItem() Function Description --//
// Client can call this function to remove item of type kAudioTrackType and
// kDataFileType. You cannot remove kPlaylistType item here.
virtual HRESULT STDMETHODCALLTYPE DeleteItem (
long lDeviceID,
IUnknown* lpItemID ) = 0;
//-- GetItem() Function Description --//
// Client can call this function to retrieve item that are kAudioTrackType
// and kDataFileType from the device to the computer. Note that client
// cannot retrieve item of type kPlaylistItem
virtual HRESULT STDMETHODCALLTYPE GetItem (
long lDeviceID,
BSTR bstrDestinationFileName,
IUnknown* lpItemID ) = 0;
//________________________ Device Properties ____________________________//
virtual HRESULT STDMETHODCALLTYPE GetDeviceProperties (
long lDeviceID,
long lDevicePropertyType,
IUnknown* lpValue ) = 0;
virtual HRESULT STDMETHODCALLTYPE SetDeviceProperties (
long lDeviceID,
long lDevicePropertyType,
IUnknown* lpValue ) = 0;
//_______________________ Playback control ______________________________//
virtual HRESULT STDMETHODCALLTYPE PlayControl (
long lDeviceID,
long lPlayOperationType,
IUnknown* lpValue ) = 0;
virtual HRESULT STDMETHODCALLTYPE QueueControl (
long lDeviceID,
long lQueueOperationType,
IUnknown* lpValue ) = 0;
};
//////////////////////////////////////////////////////////////
// ICTNomad2 Methods //
//////////////////////////////////////////////////////////////
// {368953D4-6A2F-4787-BC6F-4047A39A7557}
DEFINE_GUID(IID_ICTNomad2,
0x368953d4, 0x6a2f, 0x4787, 0xbc, 0x6f, 0x40, 0x47, 0xa3, 0x9a, 0x75, 0x57);
interface ICTNomad2 : public IUnknown
{
virtual HRESULT STDMETHODCALLTYPE Initialize() = 0;
virtual HRESULT STDMETHODCALLTYPE ShutDown() = 0;
virtual HRESULT STDMETHODCALLTYPE SetCallbackWindow(
/*[in]*/long lDeviceID,
/*[in]*/long hWnd) = 0;
virtual HRESULT STDMETHODCALLTYPE GetDeviceCount(
/*[out]*/long* lpDeviceCount) = 0;
virtual HRESULT STDMETHODCALLTYPE CancelTransfer(
/*[in]*/long lDeviceID) = 0;
virtual HRESULT STDMETHODCALLTYPE GetSDKVersion(
/*[out]*/IUnknown* lpVersion) = 0;
//__________________________ Querying Item ______________________________//
virtual HRESULT STDMETHODCALLTYPE FindFirstItem (
long lDeviceID,
IUnknown* lParentItemID,
IUnknown* lpItemID ) = 0;
virtual HRESULT STDMETHODCALLTYPE FindNextItem (
long lDeviceID,
IUnknown* lParentItemID,
IUnknown* lpItemID ) = 0;
//_____________________ Getting Item Attributes __________________________//
//-- GetItemAttribute() Function Description --//
// This function returns the TrackInfo data for all Item type. But for
// kDataFileType and kPlaylistFileType, the TrackInfo data contain only
// file name, file type and file size. In contrast, the item attribute
// for a kAudioTrackType may contain all information similar to the ID3tag
// information that a typical MP3 file has.
virtual HRESULT STDMETHODCALLTYPE GetItemAttribute (
long lDeviceID,
IUnknown* lpItemID,
long lInItemInfoSize,
long* lOutItemInfoSize,
IUnknown* lpItemInfo ) = 0;
//____________________________ Item Management ___________________________//
//-- AddItem() Function Description --//
// This function initiates the file download from the computer to the
// device. Client should call this function to download audio tracks
// like MP3, WMA and WAVE and data files. Client are not allow
// to download an item of kPlaylistType, use AddItemsToParentItem to add
// item of type kPlaylistType.
virtual HRESULT STDMETHODCALLTYPE AddItem (
long lDeviceID,
long lItemType,
BSTR bstrSrcFileName,
long lItemInfoSize,
IUnknown* lpItemInfo) = 0;
//-- DeleteItem() Function Description --//
// Client can call this function to remove item of type kAudioTrackType and
// kDataFileType. You cannot remove kPlaylistType item here.
virtual HRESULT STDMETHODCALLTYPE DeleteItem (
long lDeviceID,
IUnknown* lpItemID ) = 0;
//-- GetItem() Function Description --//
// Client can call this function to retrieve item that are kAudioTrackType
// and kDataFileType from the device to the computer. Note that client
// cannot retrieve item of type kPlaylistItem
virtual HRESULT STDMETHODCALLTYPE GetItem (
long lDeviceID,
BSTR bstrDestinationFileName,
IUnknown* lpItemID ) = 0;
//________________________ Device Properties ____________________________//
virtual HRESULT STDMETHODCALLTYPE GetDeviceProperties (
long lDeviceID,
long lDevicePropertyType,
IUnknown* lpValue ) = 0;
virtual HRESULT STDMETHODCALLTYPE SetDeviceProperties (
long lDeviceID,
long lDevicePropertyType,
IUnknown* lpValue ) = 0;
};
#ifdef __cplusplus
}
#endif // __cplusplus
#endif
Binary file not shown.
+181
View File
@@ -0,0 +1,181 @@
//#define PLUGIN_NAME "Nullsoft Creative NJB Plug-in"
#define PLUGIN_VERSION L"0.57"
#include "NJBDevice.h"
#include "../Winamp/wa_ipc.h"
#define WM_PMP_NJB_DEVICE_CONNECTED (WM_USER+23)
int init();
void quit();
intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3);
PMPDevicePlugin plugin = {PMPHDR_VER, 0, init, quit, MessageProc};
LRESULT CALLBACK CallbackWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
C_ItemList devices;
// wasabi based services for localisation support
api_language *WASABI_API_LNG = 0;
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
ICTJukebox2 * m_pCTJukebox2 = NULL;
HWND mainMessageWindow = 0;
static bool classRegistered = 0;
HWND CreateDummyWindow()
{
if (!classRegistered)
{
WNDCLASSW wc = {0, };
wc.style = 0;
wc.lpfnWndProc = CallbackWndProc;
wc.hInstance = plugin.hDllInstance;
wc.hIcon = 0;
wc.hCursor = NULL;
wc.lpszClassName = L"pmp_njb_window";
if (!RegisterClassW(&wc))
return 0;
classRegistered = true;
}
HWND dummy = CreateWindowW(L"pmp_njb_window", L"pmp_njb_window", 0, 0, 0, 0, 0, NULL, NULL, plugin.hDllInstance, NULL);
return dummy;
}
int init()
{
waServiceFactory *sf = plugin.service->service_getServiceByGuid(languageApiGUID);
if (sf) WASABI_API_LNG = reinterpret_cast<api_language*>(sf->getInterface());
// need to have this initialised before we try to do anything with localisation features
WASABI_API_START_LANG(plugin.hDllInstance,PmpNJBLangGUID);
static wchar_t szDescription[256];
swprintf(szDescription, ARRAYSIZE(szDescription),
WASABI_API_LNGSTRINGW(IDS_NULLSOFT_CREATIVE_NJB), PLUGIN_VERSION);
plugin.description = szDescription;
OleInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_CTJukeBox2, NULL, CLSCTX_ALL, IID_ICTJukebox2, (void**) & m_pCTJukebox2);
if (hr != S_OK) return 0;
hr = m_pCTJukebox2->Initialize2();
if (hr != S_OK)
{
m_pCTJukebox2->Release();
m_pCTJukebox2=0;
return 0;
}
mainMessageWindow = CreateDummyWindow();
m_pCTJukebox2->SetCallbackWindow2(0, (long)mainMessageWindow);
long devCount = 0;
m_pCTJukebox2->GetDeviceCount2(&devCount);
for (long i = 1; i <= devCount; i++)
PostMessage(mainMessageWindow, WM_PMP_NJB_DEVICE_CONNECTED, i, 0);
return 0;
}
void quit()
{
if (m_pCTJukebox2)
{
m_pCTJukebox2->ShutDown2();
m_pCTJukebox2->Release();
m_pCTJukebox2 = 0;
}
DestroyWindow(mainMessageWindow);
OleUninitialize();
}
LRESULT CALLBACK CallbackWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_PMP_NJB_DEVICE_CONNECTED:
{
new NJBDevice((int)wParam);
}
break;
case WM_DAPSDK_JUKEBOX_REMOVAL:
{
long devCount = 0;
if (m_pCTJukebox2->GetDeviceCount2(&devCount) == S_OK)
{
if (devCount == 0) // TODO benski> shouldn't we always register for messages?
m_pCTJukebox2->SetCallbackWindow2(0, (long)mainMessageWindow);
for (long i = 0; i < devices.GetSize(); /*i++*/)
{
NJBDevice * dev = (NJBDevice *)devices.Get(i);
bool attached = false;
for (long j = 1; j <= devCount; j++)
{
BYTE * ptr = NULL;
if (m_pCTJukebox2->GetDeviceProperties(j, kDeviceSerialNumberValue, (IUnknown*)ptr) == S_OK)
{
if (memcmp(ptr, dev->serial, 16) == 0)
{
attached = true;
dev->id = j;
break;
}
//free(ptr);
}
}
if (!attached)
{
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)dev,PMP_IPC_DEVICEDISCONNECTED);
delete dev;
}
else
i++;
}
}
}
break;
case WM_DAPSDK_JUKEBOX_ARRIVAL:
{
long devCount = 0;
if (m_pCTJukebox2->GetDeviceCount2(&devCount) == S_OK)
new NJBDevice(devCount);
}
break;
default:
{
for (int i = 0; i < devices.GetSize(); i++)
{
NJBDevice * dev = (NJBDevice *)devices.Get(i);
if (dev->messageWindow == hwnd)
return dev->WindowMessage(hwnd, uMsg, wParam, lParam);
}
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);;
}
intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3) {
switch(msg) {
case PMP_DEVICECHANGE:
return 0;
case PMP_NO_CONFIG:
return TRUE;
case PMP_CONFIG:
return 0;
}
return 0;
}
extern "C" {
__declspec( dllexport ) PMPDevicePlugin * winampGetPMPDevicePlugin(){return &plugin;}
__declspec( dllexport ) int winampUninstallPlugin(HINSTANCE hDllInst, HWND hwndDlg, int param) {
int i = devices.GetSize();
while(i-- > 0) ((Device*)devices.Get(i))->Close();
return PMP_PLUGIN_UNINSTALL_NOW;
}
};
+109
View File
@@ -0,0 +1,109 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
#if defined(APSTUDIO_INVOKED) || defined(DISABLED)
#if defined(APSTUDIO_INVOKED)
IDD_INVISI$(DISABLED) DIALOGEX 0, 0, 5, 5
#else
IDD_INVISI DIALOGEX 0, 0, 5, 5
#endif
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
END
#endif
/////////////////////////////////////////////////////////////////////////////
//
// RCDATA
//
IDR_ZEN_ICON RCDATA ".\\resources\\zenIcon.png"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_NULLSOFT_CREATIVE_NJB "Nullsoft Creative NJB Plug-in v%s"
65535 "{4F5B2300-19D1-4390-BE04-89019441100B}"
END
STRINGTABLE
BEGIN
IDS_NJB_LOADING "NJB Loading..."
IDS_TRANSFERRING_PERCENT "Transferring %d%%"
IDS_DONE "Done"
IDS_ERROR "Error"
IDS_TRANSFERRING "Transferring..."
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
+30
View File
@@ -0,0 +1,30 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29709.97
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pmp_njb", "pmp_njb.vcxproj", "{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}.Debug|Win32.ActiveCfg = Debug|Win32
{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}.Debug|Win32.Build.0 = Debug|Win32
{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}.Debug|x64.ActiveCfg = Debug|x64
{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}.Debug|x64.Build.0 = Debug|x64
{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}.Release|Win32.ActiveCfg = Release|Win32
{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}.Release|Win32.Build.0 = Release|Win32
{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}.Release|x64.ActiveCfg = Release|x64
{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {651853BB-3138-4841-BD5B-ACF5165F9161}
EndGlobalSection
EndGlobal
@@ -0,0 +1,315 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0D2DCCBD-FF58-4A04-BC53-D6208D5EB3E4}</ProjectGuid>
<RootNamespace>pmp_njb</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\replicant;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<GenerateMapFile>false</GenerateMapFile>
<MapExports>false</MapExports>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\replicant;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<FunctionLevelLinking>true</FunctionLevelLinking>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DisableSpecificWarnings>4302;4311;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<GenerateMapFile>false</GenerateMapFile>
<MapExports>false</MapExports>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\replicant;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\replicant;..\..\..\Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;ML_ex_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope>
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
<ObjectFileName>$(IntDir)</ObjectFileName>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4302;4311;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Culture>0x040c</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;wsock32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<MapFileName>$(IntDir)$(TargetName).map</MapFileName>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\General\gen_ml\itemlist.cpp" />
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="NJBDevice.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\General\gen_ml\itemlist.h" />
<ClInclude Include="..\..\General\gen_ml\ml.h" />
<ClInclude Include="..\..\Library\ml_pmp\pmp.h" />
<ClInclude Include="NJBDevice.h" />
<ClInclude Include="Nmsdk.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_njb.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="resources\zenIcon.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\Wasabi\Wasabi.vcxproj">
<Project>{3e0bfa8a-b86a-42e9-a33f-ec294f823f7f}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NJBDevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\itemlist.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\General\gen_ml\ml_lib.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="NJBDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Nmsdk.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\General\gen_ml\itemlist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\General\gen_ml\ml.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\Library\ml_pmp\pmp.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{19f63d8f-2d94-424b-b8e5-1ae189920736}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{675c67be-1ca6-4f01-aeb3-6b9329201724}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{df88e072-b108-4287-9243-92c4883b420e}</UniqueIdentifier>
</Filter>
<Filter Include="Image Files">
<UniqueIdentifier>{a2c922b0-d514-4e40-8e03-932a77c3e2fa}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Image Include="resources\zenIcon.png">
<Filter>Image Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_njb.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
+23
View File
@@ -0,0 +1,23 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by pmp_njb1.rc
//
#define IDS_NJB_LOADING 1
#define IDS_TRANSFERRING_PERCENT 2
#define IDS_DONE 3
#define IDS_ERROR 4
#define IDS_TRANSFERRING 5
#define IDD_INVISI 9
#define IDR_ZEN_ICON 103
#define IDS_NULLSOFT_CREATIVE_NJB 65534
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 108
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Some files were not shown because too many files have changed in this diff Show More