Initial community commit
@@ -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
|
||||
@@ -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
|
||||
|
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
After Width: | Height: | Size: 197 B |
|
After Width: | Height: | Size: 5.6 KiB |
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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__
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 199 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 192 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 195 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 186 B |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 193 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 187 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 182 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 230 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 119 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 233 B |
@@ -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);
|
||||
}
|
||||
*/
|
||||
@@ -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);
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
After Width: | Height: | Size: 238 B |