diff options
Diffstat (limited to 'Src/Plugins/Portable/pmp_njb')
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/NJBDevice.cpp | 714 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/NJBDevice.h | 168 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/NOMAD DAP PC SDK v3_5.pdf | bin | 0 -> 1469440 bytes | |||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/Nmsdk.h | 922 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/ctnmjb2.dll | bin | 0 -> 126976 bytes | |||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/main.cpp | 181 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/pmp_njb.rc | 109 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/pmp_njb.sln | 30 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/pmp_njb.vcxproj | 315 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/pmp_njb.vcxproj.filters | 61 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/resource.h | 23 | ||||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/resources/zenIcon.png | bin | 0 -> 238 bytes | |||
-rw-r--r-- | Src/Plugins/Portable/pmp_njb/version.rc2 | 39 |
13 files changed, 2562 insertions, 0 deletions
diff --git a/Src/Plugins/Portable/pmp_njb/NJBDevice.cpp b/Src/Plugins/Portable/pmp_njb/NJBDevice.cpp new file mode 100644 index 00000000..4eb0d41d --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/NJBDevice.cpp @@ -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; +}
\ No newline at end of file diff --git a/Src/Plugins/Portable/pmp_njb/NJBDevice.h b/Src/Plugins/Portable/pmp_njb/NJBDevice.h new file mode 100644 index 00000000..d42b4070 --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/NJBDevice.h @@ -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_
\ No newline at end of file diff --git a/Src/Plugins/Portable/pmp_njb/NOMAD DAP PC SDK v3_5.pdf b/Src/Plugins/Portable/pmp_njb/NOMAD DAP PC SDK v3_5.pdf Binary files differnew file mode 100644 index 00000000..b044b758 --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/NOMAD DAP PC SDK v3_5.pdf diff --git a/Src/Plugins/Portable/pmp_njb/Nmsdk.h b/Src/Plugins/Portable/pmp_njb/Nmsdk.h new file mode 100644 index 00000000..892e04bb --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/Nmsdk.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 + diff --git a/Src/Plugins/Portable/pmp_njb/ctnmjb2.dll b/Src/Plugins/Portable/pmp_njb/ctnmjb2.dll Binary files differnew file mode 100644 index 00000000..1d7d458a --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/ctnmjb2.dll diff --git a/Src/Plugins/Portable/pmp_njb/main.cpp b/Src/Plugins/Portable/pmp_njb/main.cpp new file mode 100644 index 00000000..53998610 --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/main.cpp @@ -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; + } +};
\ No newline at end of file diff --git a/Src/Plugins/Portable/pmp_njb/pmp_njb.rc b/Src/Plugins/Portable/pmp_njb/pmp_njb.rc new file mode 100644 index 00000000..47812072 --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/pmp_njb.rc @@ -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 + diff --git a/Src/Plugins/Portable/pmp_njb/pmp_njb.sln b/Src/Plugins/Portable/pmp_njb/pmp_njb.sln new file mode 100644 index 00000000..baa96ce9 --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/pmp_njb.sln @@ -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 diff --git a/Src/Plugins/Portable/pmp_njb/pmp_njb.vcxproj b/Src/Plugins/Portable/pmp_njb/pmp_njb.vcxproj new file mode 100644 index 00000000..7a12022e --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/pmp_njb.vcxproj @@ -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>
\ No newline at end of file diff --git a/Src/Plugins/Portable/pmp_njb/pmp_njb.vcxproj.filters b/Src/Plugins/Portable/pmp_njb/pmp_njb.vcxproj.filters new file mode 100644 index 00000000..1eb41b59 --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/pmp_njb.vcxproj.filters @@ -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>
\ No newline at end of file diff --git a/Src/Plugins/Portable/pmp_njb/resource.h b/Src/Plugins/Portable/pmp_njb/resource.h new file mode 100644 index 00000000..6f76d97a --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/resource.h @@ -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 diff --git a/Src/Plugins/Portable/pmp_njb/resources/zenIcon.png b/Src/Plugins/Portable/pmp_njb/resources/zenIcon.png Binary files differnew file mode 100644 index 00000000..7352c626 --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/resources/zenIcon.png diff --git a/Src/Plugins/Portable/pmp_njb/version.rc2 b/Src/Plugins/Portable/pmp_njb/version.rc2 new file mode 100644 index 00000000..7ff08345 --- /dev/null +++ b/Src/Plugins/Portable/pmp_njb/version.rc2 @@ -0,0 +1,39 @@ + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// +#include "../../../Winamp/buildType.h" +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,57,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,57,0,0" + VALUE "InternalName", "Nullsoft Creative NJB" + VALUE "LegalCopyright", "Copyright © 2006-2023 Winamp SA" + VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA" + VALUE "OriginalFilename", "pmp_njb.dll" + VALUE "ProductName", "Winamp" + VALUE "ProductVersion", STR_WINAMP_PRODUCTVER + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END |