Initial community commit

This commit is contained in:
Jef
2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit 20d28e80a5
16810 changed files with 4640254 additions and 2 deletions

View File

@ -0,0 +1,53 @@
#include "ConnectActivity.h"
#include "resource.h"
#include "api.h"
#include <strsafe.h>
BOOL ConnectActivity::GetActive()
{
return TRUE;
}
BOOL ConnectActivity::GetCancelable()
{
return FALSE;
}
HRESULT ConnectActivity::GetProgress(unsigned int *percentCompleted)
{
return E_NOTIMPL;
}
HRESULT ConnectActivity::GetDisplayName(wchar_t *buffer, size_t bufferMax)
{
if (NULL == buffer)
return E_POINTER;
WASABI_API_LNGSTRINGW_BUF(IDS_ACTIVITY_CONNECT, buffer, bufferMax);
return S_OK;
}
HRESULT ConnectActivity::GetStatus(wchar_t *buffer, size_t bufferMax)
{
if (NULL == buffer)
return E_POINTER;
WASABI_API_LNGSTRINGW_BUF(IDS_ACTIVITY_CONNECT_DESC, buffer, bufferMax);
return S_OK;
}
HRESULT ConnectActivity::Cancel(HWND hostWindow)
{
return E_NOTIMPL;
}
#define CBCLASS ConnectActivity
START_DISPATCH;
CB(API_GETACTIVE, GetActive);
CB(API_GETCANCELABLE, GetCancelable);
CB(API_GETPROGRESS, GetProgress);
CB(API_GETDISPLAYNAME, GetDisplayName);
CB(API_GETSTATUS, GetStatus);
CB(API_CANCEL, Cancel);
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,16 @@
#pragma once
#include "../devices/ifc_deviceactivity.h"
class ConnectActivity : public ifc_deviceactivity
{
public:
BOOL GetActive();
BOOL GetCancelable();
HRESULT GetProgress(unsigned int *percentCompleted);
HRESULT GetDisplayName(wchar_t *buffer, size_t bufferMax);
HRESULT GetStatus(wchar_t *buffer, size_t bufferMax);
HRESULT Cancel(HWND hostWindow);
protected:
RECVS_DISPATCH;
};

View File

@ -0,0 +1,201 @@
#include "InfoDownloader.h"
#include "api.h"
#include "main.h"
#include "images.h"
#include "InfoDownloader.h"
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
#include <api/service/waServiceFactory.h>
#include <strsafe.h>
void OnInfoDownloadDone(InfoDownloader *_info);
void DeviceInfo_Init(DeviceInfo *device_info)
{
device_info->id=0;
device_info->modelInfo=NULL;
device_info->total_space=0;
device_info->used_space=0;
device_info->model[0]=0;
device_info->manufacturer[0]=0;
device_info->name[0]=0;
device_info->product[0]=0;
}
void DeviceInfo_Copy(DeviceInfo *dest, const DeviceInfo *source)
{
dest->id=source->id;
dest->modelInfo=source->modelInfo;
dest->total_space=source->total_space;
dest->used_space=source->used_space;
StringCbCopy(dest->model, sizeof(dest->model), source->model);
StringCbCopy(dest->manufacturer, sizeof(dest->manufacturer), source->manufacturer);
StringCbCopy(dest->name, sizeof(dest->name), source->name);
StringCbCopy(dest->product, sizeof(dest->product), source->product);
}
DeviceXML::DeviceXML()
{
DeviceInfo_Init(&device_info);
}
InfoXML::InfoXML(obj_xml *parser) : parser(parser)
{
parser->xmlreader_registerCallback(L"info\fdevice", this);
parser->xmlreader_registerCallback(L"info\fspace", this);
}
InfoXML::~InfoXML()
{
parser->xmlreader_unregisterCallback(this);
}
void DeviceXML::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
if (!wcscmp(xmltag, L"device"))
{
const wchar_t *value = params->getItemValue(L"id");
if (value)
device_info.id = _wcstoui64(value, 0, 16);
value = params->getItemValue(L"manufacturer");
if (value)
StringCbCopyW(device_info.manufacturer, sizeof(device_info.manufacturer), value);
value = params->getItemValue(L"model");
if (value)
StringCbCopyW(device_info.model, sizeof(device_info.model), value);
value = params->getItemValue(L"name");
if (value)
StringCbCopyW(device_info.name, sizeof(device_info.name), value);
value = params->getItemValue(L"product");
if (value)
StringCbCopyW(device_info.product, sizeof(device_info.product), value);
device_info.modelInfo = FindModelInfo(device_info.manufacturer, device_info.model, FALSE);
}
else if (!wcscmp(xmltag, L"space"))
{
const wchar_t *value = params->getItemValue(L"total");
if (value)
{
device_info.total_space = _wtoi64(value);
}
value = params->getItemValue(L"used");
if (value)
{
device_info.used_space = _wtoi64(value);
}
}
}
WifiDevice *InfoXML::CreateDevice(uint64_t device_id_check, const char *root_url)
{
if (device_info.id == device_id_check)
{
return new WifiDevice(root_url, &device_info);
}
return 0;
}
/* ------------------------------------------------------------------------------------------------------------ */
InfoDownloader::InfoDownloader(const char *_root_url, uint64_t id, Wasabi2::nx_string_t usn) : id(id)
{
this->usn = NXStringRetain(usn);
root_url = strdup(_root_url);
done=0;
waServiceFactory *parserFactory = plugin.service->service_getServiceByGuid(obj_xmlGUID);
if (parserFactory)
parser = (obj_xml *)parserFactory->getInterface();
parser->xmlreader_setCaseSensitive();
info = new InfoXML(parser);
parser->xmlreader_open();
}
InfoDownloader::~InfoDownloader()
{
NXStringRelease(usn);
waServiceFactory *parserFactory = plugin.service->service_getServiceByGuid(obj_xmlGUID);
if (parserFactory)
{
delete info;
parser->xmlreader_close();
parserFactory->releaseInterface(parser);
}
free(root_url);
}
void InfoDownloader::OnInit(DownloadToken token)
{
if (done)
{
WAC_API_DOWNLOADMANAGER->CancelDownload(token);
return;
}
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
jnet->AddHeaderValue("X-Winamp-ID", winamp_id_str);
jnet->AddHeaderValue("X-Winamp-Name", winamp_name);
}
}
void InfoDownloader::OnData(DownloadToken token, void *data, size_t datalen)
{
if (done)
{
WAC_API_DOWNLOADMANAGER->CancelDownload(token);
return;
}
if (parser->xmlreader_feed(data, datalen) != OBJ_XML_SUCCESS)
{
WAC_API_DOWNLOADMANAGER->CancelDownload(token);
}
}
void InfoDownloader::OnCancel(DownloadToken token)
{
done=2;
OnInfoDownloadDone(this);
}
void InfoDownloader::OnError(DownloadToken token, int error)
{
// TODO
done=2;
OnInfoDownloadDone(this);
}
void InfoDownloader::OnFinish(DownloadToken token)
{
if (!done)
{
parser->xmlreader_feed(0, 0);
}
done=1;
OnInfoDownloadDone(this);
}
bool InfoDownloader::Done(WifiDevice **out_device)
{
if (done != 1)
return false;
*out_device = info->CreateDevice(id, root_url);
return true;
}
void InfoDownloader::Cancel()
{
done=2;
}

View File

@ -0,0 +1,51 @@
#pragma once
#include "device.h"
#include "../xml/obj_xml.h"
#include "../Components/wac_downloadManager/DownloadCallbackT.h"
#include "WifiDevice.h"
#include "../xml/ifc_xmlreadercallbackT.h"
#include "main.h"
namespace Wasabi2
{
#include "nx/nxstring.h"
}
class DeviceXML : public ifc_xmlreadercallbackT<DeviceXML>
{
public:
DeviceXML();
void xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
DeviceInfo device_info;
};
class InfoXML : public DeviceXML
{
public:
InfoXML(obj_xml *parser);
~InfoXML();
WifiDevice *CreateDevice(uint64_t device_id_check, const char *root_url);
private:
obj_xml *parser;
};
class InfoDownloader : public DownloadCallbackT<InfoDownloader>
{
public:
InfoDownloader(const char *root_url, uint64_t id, Wasabi2::nx_string_t usn);
~InfoDownloader();
void OnInit(DownloadToken token);
void OnData(DownloadToken token, void *data, size_t datalen);
void OnCancel(DownloadToken token);
void OnError(DownloadToken token, int error);
void OnFinish(DownloadToken token);
bool Done(WifiDevice **device);
void Cancel();
uint64_t id;
Wasabi2::nx_string_t usn;
private:
char *root_url;
obj_xml *parser;
InfoXML *info;
volatile int done; // 1 for successfully done, 2 for cancelled/error
};

View File

@ -0,0 +1,147 @@
#include "api.h"
#include "..\..\..\replicant\jnetlib\multicastlisten.h"
#include "jnetlib/util.h"
#include "InfoDownloader.h"
#include "nu/AutoChar.h"
#include <vector>
#include "nu/AutoLock.h"
namespace Wasabi2
{
#include "ssdp/cb_ssdp.h"
}
#include <windows.h>
static nu::LockGuard connections_guard;
struct Connection
{
Connection()
{
usn = 0;
location = 0;
device = 0;
downloader = 0;
}
Wasabi2::nx_string_t usn;
Wasabi2::nx_uri_t location;
WifiDevice *device;
InfoDownloader *downloader;
};
typedef std::vector<Connection> Connections;
static Connections connections;
static volatile int killswitch;
static Connection &FindUSN(Wasabi2::nx_string_t usn)
{
for (size_t i=0;i<connections.size();i++)
{
if (!Wasabi2::NXStringKeywordCompare(connections[i].usn, usn))
{
return connections[i];
}
}
Connection dummy;
dummy.usn = NXStringRetain(usn);
connections.push_back(dummy);
return connections[connections.size()-1];
}
class WAFAListener : public Wasabi2::cb_ssdp
{
void WASABICALL SSDPCallback_OnServiceConnected(Wasabi2::nx_uri_t location, Wasabi2::nx_string_t type, Wasabi2::nx_string_t usn);
void WASABICALL SSDPCallback_OnServiceDisconnected(Wasabi2::nx_string_t usn);
};
void WAFAListener::SSDPCallback_OnServiceConnected(Wasabi2::nx_uri_t location, Wasabi2::nx_string_t type, Wasabi2::nx_string_t usn)
{
if (!Wasabi2::NXStringKeywordCompareWithCString(type, "urn:nullsoft.com:device:Android:1"))
{
nu::AutoLock auto_lock(connections_guard);
Connection &connection = FindUSN(usn);
connection.location = Wasabi2::NXURIRetain(location);
uint64_t id = _wcstoui64(usn->string, 0, 16);
AutoChar cached_location(location->string);
InfoDownloader *downloader = new InfoDownloader(cached_location, id, usn);
connection.downloader = downloader;
WAC_API_DOWNLOADMANAGER->DownloadEx(cached_location, downloader, api_downloadManager::DOWNLOADEX_CALLBACK);
}
}
void WAFAListener::SSDPCallback_OnServiceDisconnected(Wasabi2::nx_string_t usn)
{
nu::AutoLock auto_lock(connections_guard);
Connection &connection = FindUSN(usn);
if (connection.device)
{
connection.device->OnDisconnect();
connection.device->Release();
connection.device = 0;
}
if (connection.downloader)
{
connection.downloader->Cancel();
connection.downloader->Release();
connection.downloader = 0;
}
}
void OnInfoDownloadDone(InfoDownloader *_info)
{
nu::AutoLock auto_lock(connections_guard);
Connection &connection = FindUSN(_info->usn);
WifiDevice *device = 0;
if (connection.downloader && connection.downloader->Done(&device))
{
connection.device = device;
connection.downloader->Release();
connection.downloader = 0;
}
else
{
if (connection.location)
{
// requeue download request, TODO: but might want to wait a bit
AutoChar cached_location(connection.location->string);
WAC_API_DOWNLOADMANAGER->DownloadEx(cached_location, connection.downloader, api_downloadManager::DOWNLOADEX_CALLBACK);
}
}
}
static WAFAListener wafa_ssdp_callback;
void StartListenServer()
{
if (REPLICANT_API_SSDP)
{
REPLICANT_API_SSDP->RegisterCallback(&wafa_ssdp_callback);
}
}
void StopListenServer()
{
nu::AutoLock auto_lock(connections_guard);
for (size_t i=0;i<connections.size();i++)
{
NXStringRelease(connections[i].usn);
NXURIRelease(connections[i].location);
if (connections[i].downloader)
{
connections[i].downloader->Cancel();
connections[i].downloader->Release();
}
if (connections[i].device)
connections[i].device->Release();
}
connections.clear();
}

View File

@ -0,0 +1,87 @@
#include "Pair.h"
#include "api.h"
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
#include "main.h"
#include "WifiDevice.h"
#include <strsafe.h>
PairDownloader::PairDownloader(WifiDevice *device) : device(device)
{
device->AddRef();
}
PairDownloader::~PairDownloader()
{
}
void PairDownloader::OnInit(DownloadToken token)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
jnet->AddHeaderValue("X-Winamp-ID", winamp_id_str);
jnet->AddHeaderValue("X-Winamp-Name", winamp_name);
}
}
void PairDownloader::OnData(DownloadToken token, void *data, size_t datalen)
{
}
void PairDownloader::OnCancel(DownloadToken token)
{
device->OnConnectionFailed();
device->Release();
Release();
}
void PairDownloader::OnError(DownloadToken token, int error)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
jnet->getreplycode();
}
device->OnConnectionFailed();
device->Release();
Release();
}
void PairDownloader::OnFinish(DownloadToken token)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
if (jnet->getreplycode() == 202)
{
device->OnPaired();
device->Release();
Release();
return;
}
}
device->OnConnectionFailed();
device->Release();
Release();
}
bool IsPaired(uint64_t id)
{
wchar_t pair_name[64] = {0};
StringCbPrintfW(pair_name, sizeof(pair_name), L"%016I64x", id);
if (GetPrivateProfileInt(L"pairs", pair_name, 0, inifile) == 0)
return false;
return true;
}
void SetPaired(uint64_t id, bool status)
{
wchar_t pair_name[64] = {0};
StringCbPrintfW(pair_name, sizeof(pair_name), L"%016I64x", id);
if (status)
WritePrivateProfileString(L"pairs", pair_name, L"1", inifile);
else
WritePrivateProfileString(L"pairs", pair_name, L"0", inifile);
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "../nu/refcount.h"
#include "../Components/wac_downloadManager/DownloadCallbackT.h"
class WifiDevice;
class PairDownloader : public DownloadCallbackT<PairDownloader>
{
public:
PairDownloader(WifiDevice *device);
~PairDownloader();
void OnInit(DownloadToken token);
void OnData(DownloadToken token, void *data, size_t datalen);
void OnCancel(DownloadToken token);
void OnError(DownloadToken token, int error);
void OnFinish(DownloadToken token);
private:
WifiDevice *device;
};
bool IsPaired(uint64_t id);
void SetPaired(uint64_t id, bool status);

View File

@ -0,0 +1,150 @@
#include "PlaylistSync.h"
#include "api.h"
#include "../nu/AutoUrl.h"
#include "main.h"
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
#include <strsafe.h>
/* classes and utility functions to notifying the device of playlist modifications */
class SimpleCallback : public ifc_downloadManagerCallback
{
public:
void OnInit(DownloadToken token)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
jnet->AddHeaderValue("X-Winamp-ID", winamp_id_str);
jnet->AddHeaderValue("X-Winamp-Name", winamp_name);
}
}
RECVS_DISPATCH;
};
#define CBCLASS SimpleCallback
START_DISPATCH;
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONINIT, OnInit)
END_DISPATCH;
#undef CBCLASS
class NewPlaylistCallback : public ifc_downloadManagerCallback
{
public:
NewPlaylistCallback()
{
event = CreateEvent(NULL, TRUE, FALSE, NULL);
location=0;
}
~NewPlaylistCallback()
{
CloseHandle(event);
free(location);
}
void OnInit(DownloadToken token)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
jnet->AddHeaderValue("X-Winamp-ID", winamp_id_str);
jnet->AddHeaderValue("X-Winamp-Name", winamp_name);
}
}
void OnCancel(DownloadToken token)
{
SetEvent(event);
}
void OnError(DownloadToken token, int error)
{
SetEvent(event);
}
void OnFinish(DownloadToken token)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
const char *jnet_location = jnet->getheader("Location");
if (jnet_location)
location = strdup(jnet_location);
}
SetEvent(event);
}
const char *Wait()
{
WaitForSingleObject(event, INFINITE);
return location;
}
HANDLE event;
char *location;
RECVS_DISPATCH;
};
#define CBCLASS NewPlaylistCallback
START_DISPATCH;
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONINIT, OnInit)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONCANCEL, OnCancel)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONERROR, OnInit)
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONFINISH, OnFinish)
END_DISPATCH;
#undef CBCLASS
static SimpleCallback simple_callback;
void Sync_AddToPlaylist(const char *root_url, const wchar_t *playlist_id, const wchar_t *song_id)
{
if ( WAC_API_DOWNLOADMANAGER )
{
char url[1024] = {0};
StringCbPrintfA(url, sizeof(url), "%s/playlist?action=add&id=%s&songid=%s", root_url, AutoUrl(playlist_id), AutoUrl(song_id));
WAC_API_DOWNLOADMANAGER->DownloadEx(url, &simple_callback, api_downloadManager::DOWNLOADEX_BUFFER);
}
}
void Sync_RemoveFromPlaylist(const char *root_url, const wchar_t *playlist_id, const wchar_t *song_id)
{
if ( WAC_API_DOWNLOADMANAGER )
{
char url[1024] = {0};
StringCbPrintfA(url, sizeof(url), "%s/playlist?action=remove&id=%s&songid=%s", root_url, AutoUrl(playlist_id), AutoUrl(song_id));
WAC_API_DOWNLOADMANAGER->DownloadEx(url, &simple_callback, api_downloadManager::DOWNLOADEX_BUFFER);
}
}
void Sync_DeletePlaylist(const char *root_url, const wchar_t *playlist_id)
{
if ( WAC_API_DOWNLOADMANAGER )
{
char url[1024] = {0};
StringCbPrintfA(url, sizeof(url), "%s/playlist?action=delete&id=%s", root_url, AutoUrl(playlist_id));
WAC_API_DOWNLOADMANAGER->DownloadEx(url, &simple_callback, api_downloadManager::DOWNLOADEX_BUFFER);
}
}
WifiPlaylist *Sync_NewPlaylist(const char *root_url, const wchar_t *playlist_name)
{
if ( WAC_API_DOWNLOADMANAGER )
{
NewPlaylistCallback new_playlist_callback;
char url[1024] = {0};
StringCbPrintfA(url, sizeof(url), "%s/playlist?action=new&name=%s", root_url, AutoUrl(playlist_name));
WAC_API_DOWNLOADMANAGER->DownloadEx(url, &new_playlist_callback, api_downloadManager::DOWNLOADEX_BUFFER);
const char *playlist_id = new_playlist_callback.Wait();
if (playlist_id)
{
return new WifiPlaylist(playlist_id, playlist_name);
}
}
return 0;
}
void Sync_RenamePlaylist(const char *root_url, const wchar_t *playlist_id, const wchar_t *playlist_name)
{
if ( WAC_API_DOWNLOADMANAGER )
{
char url[ 1024 ] = { 0 };
StringCbPrintfA( url, sizeof( url ), "%s/playlist?action=rename&id=%s&name=%s", root_url, AutoUrl( playlist_id ), AutoUrl( playlist_name ) );
WAC_API_DOWNLOADMANAGER->DownloadEx( url, &simple_callback, api_downloadManager::DOWNLOADEX_BUFFER );
}
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "WifiPlaylist.h"
/* classes and utility functions to notifying the device of playlist modifications */
void Sync_AddToPlaylist(const char *root_url, const wchar_t *playlist_id, const wchar_t *song_id);
void Sync_RemoveFromPlaylist(const char *root_url, const wchar_t *playlist_id, const wchar_t *song_id);
void Sync_DeletePlaylist(const char *root_url, const wchar_t *playlist_id);
WifiPlaylist *Sync_NewPlaylist(const char *root_url, const wchar_t *playlist_name);
void Sync_RenamePlaylist(const char *root_url, const wchar_t *playlist_id, const wchar_t *playlist_name);

View File

@ -0,0 +1,39 @@
#include "RenameDownloader.h"
#include "api.h"
#include "../nu/AutoUrl.h"
#include "main.h"
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
#include <strsafe.h>
class PingCallback : public ifc_downloadManagerCallback
{
public:
void OnInit(DownloadToken token)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
jnet->AddHeaderValue("X-Winamp-ID", winamp_id_str);
jnet->AddHeaderValue("X-Winamp-Name", winamp_name);
}
}
RECVS_DISPATCH;
};
#define CBCLASS PingCallback
START_DISPATCH;
VCB(IFC_DOWNLOADMANAGERCALLBACK_ONINIT, OnInit)
END_DISPATCH;
#undef CBCLASS
static PingCallback ping_callback;
void RenameDevice(const char *root_url, const wchar_t *new_name)
{
if ( WAC_API_DOWNLOADMANAGER )
{
char url[1024] = {0};
StringCbPrintfA(url, sizeof(url), "%s/set?nick=%s", root_url, AutoUrl(new_name));
WAC_API_DOWNLOADMANAGER->DownloadEx(url, &ping_callback, api_downloadManager::DOWNLOADEX_BUFFER);
}
}

View File

@ -0,0 +1,3 @@
#pragma once
void RenameDevice(const char *root_url, const wchar_t *new_name);

View File

@ -0,0 +1,88 @@
#include "api.h"
#include "SongDownloader.h"
#include "main.h"
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
#include <strsafe.h>
SongDownloader::SongDownloader(const wchar_t *filename, HANDLE done_event, void (*callback)(void *callbackContext, wchar_t *status), void *context)
: done_event(done_event), callback(callback), context(context)
{
hFile = CreateFile(filename, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
content_length=0;
bytes_downloaded=0;
}
SongDownloader::~SongDownloader()
{
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
}
void SongDownloader::OnInit(DownloadToken token)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
jnet->AddHeaderValue("X-Winamp-ID", winamp_id_str);
jnet->AddHeaderValue("X-Winamp-Name", winamp_name);
}
}
void SongDownloader::OnData(DownloadToken token, void *data, size_t datalen)
{
if (!content_length)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
const char *header = jnet->getheader("content-length");
if (header)
content_length = _strtoui64(header, 0, 10);
}
}
DWORD written = 0;
WriteFile(hFile, data, (DWORD)datalen, &written, 0);
bytes_downloaded+=written;
if (content_length && callback)
{
wchar_t status[128] = {0};
StringCbPrintf(status, sizeof(status), L"Transferring (%d%%)", (int)(100ULL * bytes_downloaded / content_length));
callback(context,status);
}
}
void SongDownloader::OnCancel(DownloadToken token)
{
wchar_t status[128] = {0};
// TODO: lang pack
StringCbCopy(status, sizeof(status), L"Cancelled");
callback(context,status);
SetEvent(done_event);
this->Release();
}
void SongDownloader::OnError(DownloadToken token, int error)
{
wchar_t status[128] = {0};
// TODO: lang pack
StringCbCopy(status, sizeof(status), L"Failed");
callback(context,status);
SetEvent(done_event);
this->Release();
}
void SongDownloader::OnFinish(DownloadToken token)
{
wchar_t status[128] = {0};
// TODO: lang pack
StringCbCopy(status, sizeof(status), L"Done");
callback(context,status);
SetEvent(done_event);
this->Release();
}

View File

@ -0,0 +1,24 @@
#pragma once
#include "../Components/wac_downloadManager/DownloadCallbackT.h"
class SongDownloader : public DownloadCallbackT<SongDownloader>
{
public:
SongDownloader(const wchar_t *filename, HANDLE done_event, void (*callback)(void *callbackContext, wchar_t *status), void *context);
~SongDownloader();
void OnInit(DownloadToken token);
void OnData(DownloadToken token, void *data, size_t datalen);
void OnCancel(DownloadToken token);
void OnError(DownloadToken token, int error);
void OnFinish(DownloadToken token);
private:
void (*callback)(void *callbackContext, wchar_t *status);
void *context;
HANDLE hFile, done_event;
uint64_t content_length;
uint64_t bytes_downloaded;
};

View File

@ -0,0 +1,178 @@
#include "api.h"
#include "main.h"
#include "images.h"
#include "SongListDownloader.h"
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
#include <api/service/waServiceFactory.h>
#include <strsafe.h>
WifiXML::WifiXML(obj_xml *parser) : parser(parser)
{
wifi_track = 0;
wifi_playlist = 0;
parser->xmlreader_registerCallback(L"items", this);
parser->xmlreader_registerCallback(L"items\fdevice", &info_xml);
parser->xmlreader_registerCallback(L"items\fspace", &info_xml);
parser->xmlreader_registerCallback(L"items\fitem", this);
parser->xmlreader_registerCallback(L"items\fplaylist", this);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem", this);
parser->xmlreader_registerCallback(L"items\fitem\fartist", &artist);
parser->xmlreader_registerCallback(L"items\fitem\falbum", &album);
parser->xmlreader_registerCallback(L"items\fitem\fcomposer", &composer);
parser->xmlreader_registerCallback(L"items\fitem\fduration", &duration);
parser->xmlreader_registerCallback(L"items\fitem\ftrack", &track);
parser->xmlreader_registerCallback(L"items\fitem\fyear", &year);
parser->xmlreader_registerCallback(L"items\fitem\fsize", &size);
parser->xmlreader_registerCallback(L"items\fitem\ftitle", &title);
parser->xmlreader_registerCallback(L"items\fitem\fmime", &mime_type);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\fartist", &artist);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\falbum", &album);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\fcomposer", &composer);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\fduration", &duration);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\ftrack", &track);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\fyear", &year);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\fsize", &size);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\ftitle", &title);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\fmime", &mime_type);
parser->xmlreader_registerCallback(L"items\fplaylist\fitem\fmodified", &modified);
}
WifiXML::~WifiXML()
{
parser->xmlreader_unregisterCallback(this);
parser->xmlreader_unregisterCallback(&info_xml);
parser->xmlreader_unregisterCallback(&artist);
parser->xmlreader_unregisterCallback(&album);
parser->xmlreader_unregisterCallback(&composer);
parser->xmlreader_unregisterCallback(&duration);
parser->xmlreader_unregisterCallback(&track);
parser->xmlreader_unregisterCallback(&year);
parser->xmlreader_unregisterCallback(&size);
parser->xmlreader_unregisterCallback(&title);
parser->xmlreader_unregisterCallback(&mime_type);
parser->xmlreader_unregisterCallback(&modified);
}
void WifiXML::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
if (!wcscmp(xmltag, L"item"))
{
const wchar_t *value = params->getItemValue(L"id");
if (value)
{
wifi_track = new WifiTrack;
wifi_track->id = _wcsdup(value);
}
}
else if (!wcscmp(xmltag, L"playlist"))
{
const wchar_t *value = params->getItemValue(L"id");
const wchar_t *name = params->getItemValue(L"name");
if (value && name)
{
wifi_playlist = new WifiPlaylist;
wifi_playlist->id = _wcsdup(value);
wifi_playlist->name = _wcsdup(name);
}
}
}
void WifiXML::xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag)
{
if (!wcscmp(xmltag, L"item") && wifi_track)
{
wifi_track->artist = _wcsdup(artist.GetString()); artist.Reset();
wifi_track->album = _wcsdup(album.GetString()); album.Reset();
wifi_track->composer = _wcsdup(composer.GetString()); composer.Reset();
wifi_track->duration = _wtoi(duration.GetString()); duration.Reset();
wifi_track->track = _wtoi(track.GetString()); track.Reset();
wifi_track->year = _wtoi(year.GetString()); year.Reset();
wifi_track->size = _wtoi(size.GetString()); size.Reset();
wifi_track->title = _wcsdup(title.GetString()); title.Reset();
wifi_track->mime_type = _wcsdup(mime_type.GetString()); mime_type.Reset();
wifi_track->last_updated = _wtoi64(modified.GetString()); modified.Reset();
if (wifi_playlist)
wifi_playlist->tracks.push_back(wifi_track);
else
tracks.push_back(wifi_track);
wifi_track=0;
}
else if (!wcscmp(xmltag, L"playlist") && wifi_playlist)
{
playlists.push_back(wifi_playlist);
wifi_playlist = 0;
}
}
/* ------------------------------------------------------------------------------------------------------------ */
SongListDownloader::SongListDownloader(const char *root_url, WifiDevice *wifi_device) : root_url(root_url), wifi_device(wifi_device)
{
device=0;
wifi_device->AddRef();
waServiceFactory *parserFactory = plugin.service->service_getServiceByGuid(obj_xmlGUID);
if (parserFactory)
parser = (obj_xml *)parserFactory->getInterface();
parser->xmlreader_setCaseSensitive();
wifi = new WifiXML(parser);
parser->xmlreader_open();
}
SongListDownloader::~SongListDownloader()
{
waServiceFactory *parserFactory = plugin.service->service_getServiceByGuid(obj_xmlGUID);
if (parserFactory)
{
delete wifi;
parser->xmlreader_close();
parserFactory->releaseInterface(parser);
}
}
void SongListDownloader::OnInit(DownloadToken token)
{
api_httpreceiver *jnet = WAC_API_DOWNLOADMANAGER->GetReceiver(token);
if (jnet)
{
jnet->AddHeaderValue("X-Winamp-ID", winamp_id_str);
jnet->AddHeaderValue("X-Winamp-Name", winamp_name);
}
}
void SongListDownloader::OnData(DownloadToken token, void *data, size_t datalen)
{
if (parser->xmlreader_feed(data, datalen) != OBJ_XML_SUCCESS)
{
WAC_API_DOWNLOADMANAGER->CancelDownload(token);
}
}
void SongListDownloader::OnCancel(DownloadToken token)
{
wifi_device->OnConnectionFailed();
wifi_device->Release();
this->Release();
}
void SongListDownloader::OnError(DownloadToken token, int error)
{
wifi_device->OnConnectionFailed();
wifi_device->Release();
this->Release();
}
void SongListDownloader::OnFinish(DownloadToken token)
{
parser->xmlreader_feed(0, 0);
device = new TemplateDevice(wifi_device, root_url, &wifi->info_xml.device_info, &wifi->tracks, &wifi->playlists);
wifi_device->OnConnected(device);
wifi_device->Release();
PostMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)device,PMP_IPC_DEVICECONNECTED);
this->Release();
}

View File

@ -0,0 +1,58 @@
#pragma once
#include "device.h"
#include "../xml/obj_xml.h"
#include "XMLString.h"
#include "../Components/wac_downloadManager/DownloadCallbackT.h"
#include "WifiDevice.h"
#include "../xml/ifc_xmlreadercallbackT.h"
#include "main.h"
#include "InfoDownloader.h" // for InfoXML
class WifiXML : public ifc_xmlreadercallbackT<WifiXML>
{
public:
WifiXML(obj_xml *parser);
~WifiXML();
public:
void xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag);
DeviceXML info_xml;
TemplateDevice::PlaylistsList playlists;
TemplateDevice::TrackList tracks;
private:
obj_xml *parser;
TemplateDevice *device;
XMLString artist;
XMLString album;
XMLString composer;
XMLString duration;
XMLString track;
XMLString year;
XMLString size;
XMLString title;
XMLString mime_type;
XMLString modified;
WifiTrack *wifi_track;
WifiPlaylist *wifi_playlist;
};
class SongListDownloader : public DownloadCallbackT<SongListDownloader>
{
public:
SongListDownloader(const char *root_url, WifiDevice *wifi_device);
~SongListDownloader();
void OnInit(DownloadToken token);
void OnData(DownloadToken token, void *data, size_t datalen);
void OnCancel(DownloadToken token);
void OnError(DownloadToken token, int error);
void OnFinish(DownloadToken token);
private:
obj_xml *parser;
WifiXML *wifi;
TemplateDevice *device;
WifiDevice *wifi_device;
const char *root_url;
};

View File

@ -0,0 +1,269 @@
#include "WifiDevice.h"
#include "api.h"
#include "device.h"
#include "nu/ns_wc.h"
#include "resource.h"
#include "Pair.h"
#include "images.h"
#include "modelInfo.h"
#include "SongListDownloader.h"
#include <strsafe.h>
WifiDevice::WifiDevice(const char *root_url, const DeviceInfo *in_device_info)
: url(strdup(root_url))
{
DeviceInfo_Copy(&device_info, in_device_info);
InitializeCriticalSection(&register_lock);
dead=0;
connect_active=false;
pmp_device=0;
StringCbPrintfA(id_string, sizeof(id_string), "%016I64x", device_info.id);
if (IsPaired(device_info.id))
{
char full_url[256] = {0};
StringCbPrintfA(full_url, sizeof(full_url), "%s/library", url);
WAC_API_DOWNLOADMANAGER->DownloadEx(full_url, new SongListDownloader(url, this), api_downloadManager::DOWNLOADEX_CALLBACK);
}
else
{
ifc_device *device = this;
AGAVE_API_DEVICEMANAGER->DeviceRegister(&device, 1);
}
}
WifiDevice::~WifiDevice()
{
DeleteCriticalSection(&register_lock);
}
/* ifc_device stuff */
int WifiDevice::QueryInterface(GUID interface_guid, void **object)
{
if (interface_guid == IFC_Device)
{
AddRef();
*object = (ifc_device *)this;
return 0;
}
return 1;
}
const char *WifiDevice::GetName()
{
return id_string;
}
HRESULT WifiDevice::GetDisplayName(wchar_t *buffer, size_t bufferSize)
{
StringCchCopyW(buffer, bufferSize, device_info.name);
return 0;
}
const char *WifiDevice::GetType()
{
return "portable";
}
const char *WifiDevice::GetConnection()
{
return "wifi";
}
extern ifc_devicesupportedcommandenum *command_enum;
extern ifc_devicesupportedcommandstore *command_store;
extern ifc_deviceeventmanager *device_event_manager;
HRESULT WifiDevice::EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context)
{
if (connect_active)
return E_NOTIMPL;
return command_store->Enumerate(enumerator);
}
HRESULT WifiDevice::SendCommand(const char *command, HWND hostWindow, ULONG_PTR param)
{
if (!strcmp(command, "attach"))
{
return Attach(hostWindow);
}
return 0;
}
BOOL WifiDevice::GetAttached()
{
return FALSE;
}
HRESULT WifiDevice::Attach(HWND hostWindow)
{
if (!connect_active)
{
connect_active = true;
device_event_manager->Notify_ActivityStarted(this, &connect_activity);
char full_url[256] = {0};
StringCbPrintfA(full_url, sizeof(full_url), "%s/pair", url);
WAC_API_DOWNLOADMANAGER->DownloadEx(full_url, new PairDownloader(this), api_downloadManager::DOWNLOADEX_CALLBACK);
}
return S_OK;
}
HRESULT WifiDevice::Detach(HWND hostWindow)
{
return S_OK;
}
HRESULT WifiDevice::Advise(ifc_deviceevent *handler)
{
return device_event_manager->Advise(handler);
}
HRESULT WifiDevice::Unadvise(ifc_deviceevent *handler)
{
return device_event_manager->Unadvise(handler);
}
HRESULT WifiDevice::GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height)
{
return ModelInfo_GetIconPath(device_info.modelInfo, width, height, buffer, bufferSize, TRUE);
}
void WifiDevice::OnPaired()
{
char full_url[256] = {0};
StringCbPrintfA(full_url, sizeof(full_url), "%s/library", url);
WAC_API_DOWNLOADMANAGER->DownloadEx(full_url, new SongListDownloader(url, this), api_downloadManager::DOWNLOADEX_CALLBACK);
SetPaired(device_info.id, true);
}
void WifiDevice::OnConnected(TemplateDevice *device)
{
EnterCriticalSection(&register_lock);
pmp_device = device;
connect_active = false;
device_event_manager->Notify_ActivityFinished(this, &connect_activity);
AGAVE_API_DEVICEMANAGER->DeviceUnregister(id_string);
// if we disconnected/timed out on the listen server while connecting, go ahead and close the device out
if (dead && pmp_device)
{
pmp_device->CloseAsync();
pmp_device = 0;
}
LeaveCriticalSection(&register_lock);
}
void WifiDevice::OnDisconnect()
{
// TODO: might actually need a crit sec here
EnterCriticalSection(&register_lock);
dead=1;
if (pmp_device)
{
pmp_device->CloseAsync();
pmp_device = 0;
}
else
{
AGAVE_API_DEVICEMANAGER->DeviceUnregister(id_string);
}
LeaveCriticalSection(&register_lock);
}
void WifiDevice::OnConnectionFailed()
{
EnterCriticalSection(&register_lock);
delete pmp_device;
pmp_device = 0;
ifc_device *device = NULL;
bool device_exist = false;
// see if we're already registered (e.g. we started in unpaired state)
if (AGAVE_API_DEVICEMANAGER->DeviceFind(id_string, &device) == S_OK)
{
if (device == this)
device_exist = true;
device->Release();
}
if (device_exist)
{ // if we are, then notify about activity being done
connect_active = false;
device_event_manager->Notify_ActivityFinished(this, &connect_activity);
}
else if (!dead)
{ // if we weren't registered, we thought we were paired but failed
device = this;
AGAVE_API_DEVICEMANAGER->DeviceRegister(&device, 1);
}
LeaveCriticalSection(&register_lock);
}
HRESULT WifiDevice::GetActivity(ifc_deviceactivity **activity)
{
if (connect_active)
{
*activity = &connect_activity;
return S_OK;
}
else
{
return E_FAIL;
}
}
HRESULT WifiDevice::GetTotalSpace(uint64_t *size)
{
#if 0
if (device_info.total_space)
{
*size = device_info.total_space;
return S_OK;
}
#endif
return E_NOTIMPL;
}
HRESULT WifiDevice::GetUsedSpace(uint64_t *size)
{
#if 0
if (device_info.used_space)
{
*size = device_info.used_space;
return S_OK;
}
#endif
return E_NOTIMPL;
}
HRESULT WifiDevice::GetModel(wchar_t *buffer, size_t bufferSize)
{
return ModelInfo_CopyDisplayName(device_info.modelInfo, buffer, bufferSize);
}
#define CBCLASS WifiDevice
START_DISPATCH;
CB(QUERYINTERFACE, QueryInterface);
CB(API_GETNAME, GetName);
CB(API_GETICON, GetIcon);
CB(API_GETDISPLAYNAME, GetDisplayName);
CB(API_GETTOTALSPACE, GetTotalSpace);
CB(API_GETUSEDSPACE, GetUsedSpace);
CB(API_GETTYPE, GetType);
CB(API_GETCONNECTION, GetConnection);
CB(API_ENUMERATECOMMANDS, EnumerateCommands);
CB(API_SENDCOMMAND, SendCommand);
CB(API_GETATTACHED, GetAttached);
CB(API_ATTACH, Attach);
CB(API_DETACH, Detach);
CB(API_GETACTIVITY, GetActivity);
CB(API_ADVISE, Advise);
CB(API_UNADVISE, Unadvise);
CB(API_GETMODEL, GetModel);
REFERENCE_COUNTED;
END_DISPATCH;

View File

@ -0,0 +1,64 @@
#pragma once
#include <bfc/platform/types.h>
#include "../devices/ifc_device.h"
#include "device.h"
#include "../nu/refcount.h"
#include "ConnectActivity.h"
#include "main.h"
/* this one inherits from ifc_device (not Device from ml_pmp) and is used to manage
attaching/detaching, etc from the device view */
class TemplateDevice;
class WifiDevice : public Countable<ifc_device>
{
public:
WifiDevice(const char *root_url, const DeviceInfo *device_info);
~WifiDevice();
/* --- ifc_device interface --- */
int QueryInterface(GUID interface_guid, void **object);
HRESULT GetDisplayName(wchar_t *buffer, size_t bufferSize);
const char *GetName();
HRESULT GetIcon(wchar_t *buffer, size_t bufferSize, int width, int height);
const char *GetType();
const char *GetConnection();
BOOL GetHidden();
HRESULT GetTotalSpace(uint64_t *size);
HRESULT GetUsedSpace(uint64_t *size);
BOOL GetAttached();
HRESULT Attach(HWND hostWindow);
HRESULT Detach(HWND hostWindow);
HRESULT EnumerateCommands(ifc_devicesupportedcommandenum **enumerator, DeviceCommandContext context);
HRESULT SendCommand(const char *command, HWND hostWindow, ULONG_PTR param);
HRESULT GetActiveCommand(char *buffer, size_t bufferSize);
HRESULT CancelCommand(const char *command, HWND hostWindow);
HRESULT GetCommandFlags(const char *command, DeviceCommandFlags *flags);
HRESULT Advise(ifc_deviceevent *handler);
HRESULT Unadvise(ifc_deviceevent *handler);
HWND CreateView(HWND parentWindow);
void SetNavigationItem(void *navigationItem);
void OnPaired();
void OnConnected(TemplateDevice *device);
void OnConnectionFailed();
void OnDisconnect();
HRESULT GetModel(wchar_t *buffer, size_t bufferSize);
HRESULT GetActivity(ifc_deviceactivity **activity);
REFERENCE_COUNT_IMPLEMENTATION;
private:
DeviceInfo device_info;
RECVS_DISPATCH;
char id_string[32];
char *url;
TemplateDevice *pmp_device;
ConnectActivity connect_activity;
bool connect_active;
volatile int dead;
CRITICAL_SECTION register_lock;
};

View File

@ -0,0 +1,104 @@
#include "WifiPlaylist.h"
#include "api.h"
#include "nu/AutoWide.h"
/* ---- WifiTrack ---- */
WifiTrack::WifiTrack()
{
last_updated=0;
id=0;
artist=0;
album=0;
composer=0;
duration=0;
track=0;
year=0;
size=0;
title=0;
mime_type=0;
}
WifiTrack::WifiTrack(const char *id, const itemRecordW *record, const wchar_t *filename)
{
this->id=AutoWideDup(id);
artist=_wcsdup(record->artist);
album=_wcsdup(record->album);
composer=_wcsdup(record->composer);
duration=record->length;
track=record->track;
year=record->year;
size=record->filesize;
title=_wcsdup(record->title);
wchar_t mime[128] = {0};
if (AGAVE_API_METADATA->GetExtendedFileInfo(filename, L"mime", mime, 128) && mime[0])
{
mime_type=_wcsdup(mime);
}
else
{
mime_type=0;
}
last_updated=record->lastupd;
}
WifiTrack::WifiTrack(const WifiTrack &copy)
{
id=_wcsdup(copy.id);
artist=_wcsdup(copy.artist);
album=_wcsdup(copy.album);
composer=_wcsdup(copy.composer);
duration=copy.duration;
track=copy.track;
year=copy.year;
size=copy.size;
title=_wcsdup(copy.title);
mime_type=_wcsdup(copy.mime_type);
last_updated=copy.last_updated;
}
WifiTrack::~WifiTrack()
{
free(id);
free(artist);
free(album);
free(composer);
free(title);
free(mime_type);
}
/* ---- WifiPlaylist ---- */
WifiPlaylist::WifiPlaylist()
{
id=0;
name=0;
}
WifiPlaylist::WifiPlaylist(const char *id, const wchar_t *name)
{
this->id = AutoWideDup(id);
this->name = _wcsdup(name);
}
WifiPlaylist::~WifiPlaylist()
{
free(id);
free(name);
//tracks.deleteAll();
for (auto obj : tracks)
{
delete obj;
}
tracks.clear();
}
void WifiPlaylist::SetName(const wchar_t *new_name)
{
if (name != new_name)
{
free(name);
name = _wcsdup(new_name);
}
}

View File

@ -0,0 +1,36 @@
#pragma once
#include "../../General/gen_ml/ml.h" // for itemRecordW
#include <vector>
struct WifiTrack
{
WifiTrack();
WifiTrack(const WifiTrack &copy);
~WifiTrack();
WifiTrack(const char *id, const itemRecordW *record, const wchar_t *filename);
wchar_t *id;
wchar_t *artist;
wchar_t *album;
wchar_t *composer;
int duration;
int track;
int year;
int size;
wchar_t *title;
wchar_t *mime_type;
__time64_t last_updated;
wchar_t *ext;
};
class WifiPlaylist
{
public:
WifiPlaylist();
WifiPlaylist(const char *id, const wchar_t *name);
~WifiPlaylist();
void SetName(const wchar_t *new_name);
typedef std::vector<WifiTrack*> TrackList;
TrackList tracks;
wchar_t *id;
wchar_t *name;
};

View File

@ -0,0 +1,49 @@
/** (c) Nullsoft, Inc. C O N F I D E N T I A L
** Filename:
** Project:
** Description:
** Author: Ben Allison benski@nullsoft.com
** Created:
**/
#include "XMLString.h"
#include <strsafe.h>
XMLString::XMLString()
{
data[0]=0;
}
void XMLString::Reset()
{
data[0]=0;
}
const wchar_t *XMLString::GetString()
{
return data;
}
void XMLString::StartTag(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
{
data[0]=0;
}
void XMLString::TextHandler(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *str)
{
StringCchCatW(data, XMLSTRING_SIZE, str);
}
void XMLString::ManualSet(const wchar_t *string)
{
StringCchCatW(data, XMLSTRING_SIZE, string);
}
#define CBCLASS XMLString
START_DISPATCH;
VCB(ONSTARTELEMENT, StartTag)
VCB(ONCHARDATA, TextHandler)
END_DISPATCH;
#undef CBCLASS

View File

@ -0,0 +1,28 @@
#ifndef NULLSOFT_WINAMP_XMLSTRING_H
#define NULLSOFT_WINAMP_XMLSTRING_H
#include "../xml/ifc_xmlreadercallback.h"
/*
this one is an xml callback that just saves the last encountered string
*/
#define XMLSTRING_SIZE 1024
class XMLString : public ifc_xmlreadercallback
{
public:
XMLString();
void Reset();
const wchar_t *GetString();
void ManualSet(const wchar_t *string);
private:
/* XML callbacks */
void StartTag(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
void EndTag(const wchar_t *xmlpath, const wchar_t *xmltag);
void TextHandler(const wchar_t *xmlpath, const wchar_t *xmltag, const wchar_t *str);
wchar_t data[XMLSTRING_SIZE]; // for now, we'll make it dynamic later
RECVS_DISPATCH;
};
#endif

View File

@ -0,0 +1,72 @@
#include "../../Library/ml_pmp/pmp.h"
#include "api.h"
#include <api/service/waservicefactory.h>
api_albumart *AGAVE_API_ALBUMART=0;
api_language *WASABI_API_LNG = 0;
api_application *WASABI_API_APP = 0;
HINSTANCE WASABI_API_LNG_HINST = 0, WASABI_API_ORIG_HINST = 0;
api_downloadManager *WAC_API_DOWNLOADMANAGER =0;
api_config *AGAVE_API_CONFIG=0;
api_devicemanager *AGAVE_API_DEVICEMANAGER = 0;
api_metadata *AGAVE_API_METADATA=0;
api_memmgr *WASABI_API_MEMMGR=0;
Wasabi2::api_service *WASABI2_API_SVC=0;
Wasabi2::api_ssdp *REPLICANT_API_SSDP=0;
extern PMPDevicePlugin plugin;
template <class api_T>
void ServiceBuild(api_T *&api_t, GUID factoryGUID_t)
{
if (plugin.service)
{
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
if (factory)
api_t = reinterpret_cast<api_T *>( factory->getInterface() );
}
}
template <class api_T>
void ServiceRelease(api_T *api_t, GUID factoryGUID_t)
{
if (plugin.service && api_t)
{
waServiceFactory *factory = plugin.service->service_getServiceByGuid(factoryGUID_t);
if (factory)
factory->releaseInterface(api_t);
}
api_t = NULL;
}
void WasabiInit()
{
ServiceBuild(WASABI_API_APP, applicationApiServiceGuid);
ServiceBuild(WASABI_API_LNG, languageApiGUID);
ServiceBuild( WAC_API_DOWNLOADMANAGER, DownloadManagerGUID);
ServiceBuild(AGAVE_API_CONFIG, AgaveConfigGUID);
ServiceBuild(AGAVE_API_DEVICEMANAGER, DeviceManagerGUID);
ServiceBuild(AGAVE_API_ALBUMART, albumArtGUID);
ServiceBuild(AGAVE_API_METADATA, api_metadataGUID);
ServiceBuild(WASABI_API_MEMMGR, memMgrApiServiceGuid);
ServiceBuild(WASABI2_API_SVC, Wasabi2::api_service::GetServiceGUID());
// need to have this initialised before we try to do anything with localisation features
// TODO: WASABI_API_START_LANG(plugin.hDllInstance,InAviLangGUID);
if (WASABI2_API_SVC)
WASABI2_API_SVC->GetService(&REPLICANT_API_SSDP);
}
void WasabiQuit()
{
ServiceRelease(WASABI_API_APP, applicationApiServiceGuid);
ServiceRelease(WASABI_API_LNG, languageApiGUID);
ServiceRelease( WAC_API_DOWNLOADMANAGER, DownloadManagerGUID);
ServiceRelease(AGAVE_API_CONFIG, AgaveConfigGUID);
ServiceRelease(AGAVE_API_DEVICEMANAGER, DeviceManagerGUID);
ServiceRelease(AGAVE_API_ALBUMART, albumArtGUID);
ServiceRelease(AGAVE_API_METADATA, api_metadataGUID);
ServiceRelease(WASABI_API_MEMMGR, memMgrApiServiceGuid);
ServiceRelease(WASABI2_API_SVC, Wasabi2::api_service::GetServiceGUID());
if (REPLICANT_API_SSDP)
REPLICANT_API_SSDP->Release();
}

View File

@ -0,0 +1,44 @@
#pragma once
#include "../Agave/Language/api_language.h"
#include <api/application/api_application.h>
extern api_application *applicationApi;
#define WASABI_API_APP applicationApi
#include "../Components/wac_downloadManager/wac_downloadManager_api.h"
#include "../Agave/Config/api_config.h"
extern api_config *config;
#define AGAVE_API_CONFIG config
#include "../devices/api_devicemanager.h"
extern api_devicemanager *deviceManagerApi;
#define AGAVE_API_DEVICEMANAGER deviceManagerApi
#include "../Agave/Metadata/api_metadata.h"
extern api_metadata *metadataApi;
#define AGAVE_API_METADATA metadataApi
#include "../Agave/AlbumArt/api_albumart.h"
extern api_albumart *albumArtApi;
#define AGAVE_API_ALBUMART albumArtApi
#include <api/memmgr/api_memmgr.h>
extern api_memmgr *memmgr;
#define WASABI_API_MEMMGR memmgr
namespace Wasabi2
{
#include "service/api_service.h"
#include "ssdp/api_ssdp.h"
}
extern Wasabi2::api_service *WASABI2_API_SVC;
extern Wasabi2::api_ssdp *REPLICANT_API_SSDP;
void WasabiInit();
void WasabiQuit();

View File

@ -0,0 +1,797 @@
#include "main.h"
#include "device.h"
#include "XMLString.h"
#include "api.h"
#include "../xml/obj_xml.h"
#include "../xml/ifc_xmlreaderparams.h"
#include <api/service/waServiceFactory.h>
#include "SongListDownloader.h"
#include "SongDownloader.h"
#include "RenameDownloader.h"
#include "resource.h"
#include "PlaylistSync.h"
#include "nu/AutoWide.h"
#include "images.h"
#include <mmsystem.h> // for mmioFOURCC
#include <strsafe.h>
#include <shlwapi.h>
TemplateDevice::TemplateDevice(WifiDevice *device, const char *root_url, DeviceInfo *in_device_info, TrackList *track_list, PlaylistsList *playlists_list)
: url(strdup(root_url))
{
DeviceInfo_Copy(&device_info, in_device_info);
//tracks.own(*track_list);
for (auto track : tracks)
{
delete track;
}
tracks.clear();
tracks.assign(track_list->begin(), track_list->end());
track_list->clear();
//playlists.own(*playlists_list);
for (auto playlist : playlists)
{
delete playlist;
}
playlists.clear();
playlists.assign(playlists_list->begin(), playlists_list->end());
playlists_list->clear();
transcoder=0;
transferQueueLength=0;
transcoder = (Transcoder*)SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)this,PMP_IPC_GET_TRANSCODER);
if(transcoder)
{
transcoder->AddAcceptableFormat(L"m4a");
transcoder->AddAcceptableFormat(L"mp3");
transcoder->AddAcceptableFormat(L"wav");
transcoder->AddAcceptableFormat(L"m4v");
transcoder->AddAcceptableFormat(L"mp4");
transcoder->AddAcceptableFormat(L"avi");
transcoder->AddAcceptableFormat(L"3gp");
transcoder->AddAcceptableFormat(L"mid");
transcoder->AddAcceptableFormat(L"ogg");
}
}
TemplateDevice::~TemplateDevice()
{
free(url);
//tracks.deleteAll();
for (auto track : tracks)
{
delete track;
}
tracks.clear();
//playlists.deleteAll();
for (auto playlist : playlists)
{
delete playlist;
}
playlists.clear();
if (transcoder)
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)transcoder,PMP_IPC_RELEASE_TRANSCODER);
transcoder=0;
}
__int64 TemplateDevice::getDeviceCapacityAvailable() // in bytes
{
return device_info.total_space - device_info.used_space;
}
__int64 TemplateDevice::getDeviceCapacityTotal()
{
return device_info.total_space;
}
void TemplateDevice::Eject()
{
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICEDISCONNECTED);
}
void TemplateDevice::Close()
{
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICEDISCONNECTED);
}
void TemplateDevice::CloseAsync()
{
PostMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(intptr_t)this,PMP_IPC_DEVICEDISCONNECTED);
}
int PostFile(const char *url, const wchar_t *filename, const itemRecordW *track, obj_xml *parser, int *killswitch,
void (*callback)(void *callbackContext, wchar_t *status), void *context, char *new_item_id, size_t new_item_id_len);
int PostAlbumArt(const char *url, const itemRecordW *track, obj_xml *parser, int *killswitch, void (*callback)(void *callbackContext, wchar_t *status), void *context);
static int64_t FileSize64(const 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;
}
// return 0 for success, -1 for failed or cancelled
int TemplateDevice::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
)
{
wchar_t newfile[MAX_PATH] = {0};
wchar_t *filename = track->filename;
bool delete_file = false;
if(transcoder && transcoder->ShouldTranscode(track->filename))
{
wchar_t ext[10] = {0};
int r = transcoder->CanTranscode(track->filename, ext, track->length);
if(r != 0 && r != -1)
{
transcoder->GetTempFilePath(ext,newfile);
if(transcoder->TranscodeFile(track->filename,newfile,killswitch,callback,callbackContext)) return -1;
filename = newfile;
delete_file=true;
}
}
char new_item_id[512] = {0};
char upload_url[555] = {0};
StringCbPrintfA(upload_url, sizeof(upload_url), "%s/upload", url);
if (PostFile(upload_url, filename, track, 0, killswitch, callback, callbackContext, new_item_id, 512) == 0 && new_item_id[0])
{
StringCbPrintfA(upload_url, sizeof(upload_url), "%s/albumart/%s", url, new_item_id);
PostAlbumArt(upload_url, track, 0, killswitch, callback, callbackContext);
callback(callbackContext, WASABI_API_LNGSTRINGW(IDS_COMPLETED));
WifiTrack *new_track = new WifiTrack(new_item_id, track, filename);
*songid = (songid_t)new_track;
device_info.used_space += FileSize64(filename); // TODO: count album art also. or re-query for device info
if (delete_file)
DeleteFile(filename);
return 0;
}
else
{
callback(callbackContext, L"Failed");
if (delete_file)
DeleteFile(filename);
return -1;
}
}
int TemplateDevice::trackAddedToTransferQueue(const itemRecordW *track)
{
// return 0 to accept, -1 for "not enough space", -2 for "incorrect format"
__int64 l;
if(transcoder && transcoder->ShouldTranscode(track->filename))
{
int k = transcoder->CanTranscode(track->filename, 0, track->length);
if(k == -1) return -2;
if(k == 0) l = (__int64)FileSize64(track->filename);
else l = (__int64)k;
}
else
{
l = FileSize64(track->filename);
}
int64_t avail = getDeviceCapacityAvailable();
int64_t cmp = transferQueueLength;
cmp += l;
cmp += 3000000LL;
if(cmp > avail)
return -1;
else
{
transferQueueLength += l;
return 0;
}
}
void TemplateDevice::trackRemovedFromTransferQueue(const itemRecordW *track)
{
int64_t l = FileSize64(track->filename);
if(transcoder && transcoder->ShouldTranscode(track->filename))
{
int k = transcoder->CanTranscode(track->filename, 0, track->length);
if(k != -1 && k != 0) l = (__int64)k;
}
transferQueueLength -= l;
}
// return the amount of space that will be taken up on the device by the track (once it has been tranferred)
// or 0 for incompatable. This is usually the filesize, unless you are transcoding. An estimate is acceptable.
__int64 TemplateDevice::getTrackSizeOnDevice(const itemRecordW *track)
{
if(transcoder && transcoder->ShouldTranscode(track->filename))
{
int k = transcoder->CanTranscode(track->filename, 0, track->length);
if(k != -1 && k != 0) return k;
}
return track->filesize;
}
int HTTP_Delete(const char *url);
void TemplateDevice::deleteTrack(songid_t songid)
{
// physically remove from device. Be sure to remove it from all the playlists!
WifiTrack *track = (WifiTrack *)songid;
char delete_url[1024] = {0};
StringCbPrintfA(delete_url, sizeof(delete_url), "%s/file/%S", url, track->id);
HTTP_Delete(delete_url);
again1:
for (WifiPlaylist::TrackList::iterator itr2=tracks.begin(); itr2 != tracks.end(); itr2++)
{
WifiTrack *trackitr = *itr2;
if (!wcscmp(trackitr->id, track->id))
{
tracks.erase(itr2);
if (trackitr != track)
delete trackitr;
goto again1; // iterator was invalidated
}
}
for (PlaylistsList::iterator itr=playlists.begin();itr!=playlists.end();itr++)
{
WifiPlaylist *playlist = *itr;
again2:
for (WifiPlaylist::TrackList::iterator itr2=playlist->tracks.begin(); itr2 != playlist->tracks.end(); itr2++)
{
WifiTrack *trackitr = *itr2;
if (!wcscmp(trackitr->id, track->id))
{
playlist->tracks.erase(itr2);
if (trackitr != track)
delete trackitr;
goto again2; // iterator was invalidated
}
}
}
delete track;
}
void TemplateDevice::commitChanges()
{
// optional. Will be called at a good time to save changes
}
int TemplateDevice::getPlaylistCount()
{
// always at least 1. playlistnumber 0 is the Master Playlist containing all tracks.
return 1 + (int)playlists.size();
}
// PlaylistName(0) should return the name of the device.
void TemplateDevice::getPlaylistName(int playlistnumber, wchar_t *buf, int len)
{
if (playlistnumber == 0)
{
StringCchCopy(buf, len, device_info.name);
}
else
{
WifiPlaylist *playlist = playlists[playlistnumber-1];
StringCchCopy(buf, len, playlist->name);
}
}
int TemplateDevice::getPlaylistLength(int playlistnumber)
{
if (playlistnumber == 0)
{
size_t size = tracks.size();
return (int)size;
}
else
{
WifiPlaylist *playlist = playlists[playlistnumber-1];
size_t size = playlist->tracks.size();
return (int)size;
}
}
songid_t TemplateDevice::getPlaylistTrack(int playlistnumber,int songnum)
{
if (playlistnumber == 0)
{
WifiTrack *track = tracks[songnum];
return (songid_t)track;
}
else
{
WifiPlaylist *playlist = playlists[playlistnumber-1];
WifiTrack *track = playlist->tracks[songnum];
return (songid_t)track;
}
}
void TemplateDevice::setPlaylistName(int playlistnumber, const wchar_t *buf)
{
if (playlistnumber == 0) // playlist 0 is the device itself
{
RenameDevice(url, buf);
StringCbCopy(device_info.name, sizeof(device_info.name), buf);
}
else
{
WifiPlaylist *playlist = playlists[playlistnumber-1];
playlist->SetName(buf);
Sync_RenamePlaylist(url, playlist->id, buf);
}
}
void TemplateDevice::playlistSwapItems(int playlistnumber, int posA, int posB)
{
// swap the songs at position posA and posB
// TODO: implement
}
void TemplateDevice::sortPlaylist(int playlistnumber, int sortBy)
{
// TODO: implement
}
void TemplateDevice::addTrackToPlaylist(int playlistnumber, songid_t songid)
{
// adds songid to the end of the playlist
WifiTrack *track = (WifiTrack *)songid;
if (playlistnumber == 0)
{
tracks.push_back(track);
}
else
{
playlists[playlistnumber - 1]->tracks.push_back(new WifiTrack(*track));
Sync_AddToPlaylist(url, playlists[playlistnumber-1]->id, track->id);
}
}
void TemplateDevice::removeTrackFromPlaylist(int playlistnumber, int songnum)
{
//where songnum is the position of the track in the playlist
if (playlistnumber == 0)
{
tracks.erase(tracks.begin() + songnum);
}
else
{
WifiPlaylist *playlist = playlists[playlistnumber-1];
WifiTrack *track = playlist->tracks[songnum];
Sync_RemoveFromPlaylist(url, playlist->id, track->id);
}
}
void TemplateDevice::deletePlaylist(int playlistnumber)
{
if (playlistnumber == 0)
{
}
else
{
WifiPlaylist *playlist = playlists[playlistnumber-1];
Sync_DeletePlaylist(url, playlist->id);
playlists.erase(playlists.begin() + playlistnumber-1);
}
}
int TemplateDevice::newPlaylist(const wchar_t *name)
{
// create empty playlist, returns playlistnumber. -1 for failed.
WifiPlaylist *new_playlist = Sync_NewPlaylist(url, name);
if (new_playlist)
{
playlists.push_back(new_playlist);
return (int)playlists.size();
}
return -1;
}
void TemplateDevice::getTrackArtist(songid_t songid, wchar_t *buf, int len)
{
WifiTrack *track = (WifiTrack *)songid;
StringCchCopy(buf, len, track->artist);
}
void TemplateDevice::getTrackAlbum(songid_t songid, wchar_t *buf, int len)
{
WifiTrack *track = (WifiTrack *)songid;
StringCchCopy(buf, len, track->album);
}
void TemplateDevice::getTrackTitle(songid_t songid, wchar_t *buf, int len)
{
WifiTrack *track = (WifiTrack *)songid;
StringCchCopy(buf, len, track->title);
}
int TemplateDevice::getTrackTrackNum(songid_t songid)
{
WifiTrack *track = (WifiTrack *)songid;
return track->track;
}
int TemplateDevice::getTrackDiscNum(songid_t songid)
{
// TODO: implement
return 0;
}
void TemplateDevice::getTrackGenre(songid_t songid, wchar_t * buf, int len)
{
buf[0]=0;
}
int TemplateDevice::getTrackYear(songid_t songid)
{
WifiTrack *track = (WifiTrack *)songid;
return track->year;
}
__int64 TemplateDevice::getTrackSize(songid_t songid)
{
WifiTrack *track = (WifiTrack *)songid;
return track->size;
}
int TemplateDevice::getTrackLength(songid_t songid)
{
WifiTrack *track = (WifiTrack *)songid;
return track->duration;
}
int TemplateDevice::getTrackBitrate(songid_t songid)
{
return 128;
}
int TemplateDevice::getTrackPlayCount(songid_t songid)
{
return 0;
}
int TemplateDevice::getTrackRating(songid_t songid)
{
return 0;
}
__time64_t TemplateDevice::getTrackLastPlayed(songid_t songid)
{
return 0;
}
__time64_t TemplateDevice::getTrackLastUpdated(songid_t songid)
{
WifiTrack *track = (WifiTrack *)songid;
return track->last_updated;
}
void TemplateDevice::getTrackAlbumArtist(songid_t songid, wchar_t *buf, int len)
{
buf[0]=0;
}
void TemplateDevice::getTrackPublisher(songid_t songid, wchar_t *buf, int len)
{
buf[0]=0;
}
void TemplateDevice::getTrackComposer(songid_t songid, wchar_t *buf, int len)
{
WifiTrack *track = (WifiTrack *)songid;
StringCchCopy(buf, len, track->composer);
}
int TemplateDevice::getTrackType(songid_t songid)
{
return 0;
}
void TemplateDevice::getTrackExtraInfo(songid_t songid, const wchar_t *field, wchar_t *buf, int len)
{
// TODO: implement
//optional
}
// feel free to ignore any you don't support
void TemplateDevice::setTrackArtist(songid_t songid, const wchar_t *value)
{
// TODO: implement
}
void TemplateDevice::setTrackAlbum(songid_t songid, const wchar_t *value)
{
// TODO: implement
}
void TemplateDevice::setTrackTitle(songid_t songid, const wchar_t *value)
{
// TODO: implement
}
void TemplateDevice::setTrackTrackNum(songid_t songid, int value)
{
// TODO: implement
}
void TemplateDevice::setTrackDiscNum(songid_t songid, int value)
{
// TODO: implement
}
void TemplateDevice::setTrackGenre(songid_t songid, const wchar_t *value)
{
// TODO: implement
}
void TemplateDevice::setTrackYear(songid_t songid, int year)
{
// TODO: implement
}
void TemplateDevice::setTrackPlayCount(songid_t songid, int value)
{
// TODO: implement
}
void TemplateDevice::setTrackRating(songid_t songid, int value)
{
// TODO: implement
}
void TemplateDevice::setTrackLastPlayed(songid_t songid, __time64_t value)
{
// TODO: implement
} // in unix time format
void TemplateDevice::setTrackLastUpdated(songid_t songid, __time64_t value)
{
// TODO: implement
} // in unix time format
void TemplateDevice::setTrackAlbumArtist(songid_t songid, const wchar_t *value)
{
// TODO: implement
}
void TemplateDevice::setTrackPublisher(songid_t songid, const wchar_t *value)
{
// TODO: implement
}
void TemplateDevice::setTrackComposer(songid_t songid, const wchar_t *value)
{
// TODO: implement
}
void TemplateDevice::setTrackExtraInfo(songid_t songid, const wchar_t *field, const wchar_t *value)
{
// TODO: implement
} //optional
bool TemplateDevice::playTracks(songid_t * songidList, int listLength, int startPlaybackAt, bool enqueue)
{
if(!enqueue) //clear playlist
{
SendMessage(plugin.hwndWinampParent,WM_WA_IPC,0,IPC_DELETE);
}
for(int i=0; i<listLength; i++)
{
WifiTrack*curSong = (WifiTrack *)songidList[i];
if (curSong)
{
wchar_t fn[1024] = {0};
if (curSong->mime_type && !_wcsicmp(curSong->mime_type, L"audio/mp4"))
StringCbPrintf(fn, sizeof(fn), L"%S/file/%s?=.m4a", url, curSong->id);
else if (curSong->mime_type && !_wcsicmp(curSong->mime_type, L"audio/x-ms-wma"))
StringCbPrintf(fn, sizeof(fn), L"%S/file/%s?=.wma", url, curSong->id);
else if (curSong->mime_type && (!_wcsicmp(curSong->mime_type, L"application/ogg") || !_wcsicmp(curSong->mime_type, L"audio/ogg")))
StringCbPrintf(fn, sizeof(fn), L"%S/file/%s?=.ogg", url, curSong->id);
else
StringCbPrintf(fn, sizeof(fn), L"%S/file/%s", url, curSong->id);
enqueueFileWithMetaStructW s={0};
s.filename = fn;
s.title = _wcsdup(curSong->title);
s.ext = NULL;
s.length = curSong->duration/1000;
SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s, IPC_PLAYFILEW);
}
else
{
//char titleStr[32];
//MessageBoxA(plugin.hwndWinampParent,WASABI_API_LNGSTRING(IDS_CANNOT_OPEN_FILE),
// WASABI_API_LNGSTRING_BUF(IDS_ERROR,titleStr,32),0);
}
}
if(!enqueue)
{
//play item startPlaybackAt
SendMessage(plugin.hwndWinampParent,WM_WA_IPC,startPlaybackAt,IPC_SETPLAYLISTPOS);
SendMessage(plugin.hwndWinampParent,WM_COMMAND,40047,0); //stop
SendMessage(plugin.hwndWinampParent,WM_COMMAND,40045,0); //play
}
return true;
}
static const intptr_t encoder_blacklist[] =
{
mmioFOURCC('W','M','A',' '),
mmioFOURCC('A','A','C','H'),
mmioFOURCC('A','A','C','P'),
mmioFOURCC('A','A','C','r'),
mmioFOURCC('F','L','A','C'),
mmioFOURCC('M','P','2',' '),
mmioFOURCC('A','D','T','S'),
};
intptr_t TemplateDevice::extraActions(intptr_t param1, intptr_t param2, intptr_t param3,intptr_t param4)
{
switch(param1)
{
case DEVICE_SET_ICON: // icons
{
MLTREEIMAGE * i = (MLTREEIMAGE*)param2;
const ModelInfo *modelInfo;
i->hinst = plugin.hDllInstance;
modelInfo = device_info.modelInfo;
if (NULL == modelInfo || NULL == modelInfo->smallIcon)
{
modelInfo = GetDefaultModelInfo();
if (NULL == modelInfo)
break;
}
i->resourceId = (int)(intptr_t)modelInfo->smallIcon;
}
break;
case DEVICE_CAN_RENAME_DEVICE:
return 1;
case DEVICE_GET_ICON:
ModelInfo_GetIconPath(device_info.modelInfo, (int)param2, (int)param3, (wchar_t*)param4, 260, TRUE);
break;
case DEVICE_GET_CONNECTION_TYPE:
{
const char **type = (const char **)param2;
*type = "WiFi";
return 1;
}
case DEVICE_SUPPORTS_PODCASTS:
return 1; // we don't support podcasts
case DEVICE_GET_MODEL:
ModelInfo_CopyDisplayName(device_info.modelInfo, (wchar_t*)param2, param3);
return 1;
case DEVICE_SUPPORTED_METADATA:
{
intptr_t supported = SUPPORTS_ARTIST | SUPPORTS_ALBUM | SUPPORTS_TITLE | SUPPORTS_TRACKNUM /*| SUPPORTS_DISCNUM | SUPPORTS_GENRE */|
SUPPORTS_YEAR | SUPPORTS_SIZE | SUPPORTS_LENGTH /*| SUPPORTS_BITRATE */| SUPPORTS_LASTUPDATED /*| SUPPORTS_ALBUMARTIST */|
SUPPORTS_COMPOSER /*| SUPPORTS_PUBLISHER | SUPPORTS_ALBUMART*/;
return supported;
}
break;
case DEVICE_VETO_ENCODER:
{
for (size_t i=0;i<sizeof(encoder_blacklist)/sizeof(*encoder_blacklist);i++)
{
if (param2 == encoder_blacklist[i])
return 1;
}
}
return 0;
}
// TODO: implement more
return 0;
}
bool TemplateDevice::copyToHardDriveSupported()
{
return true;
}
__int64 TemplateDevice::songSizeOnHardDrive(songid_t song)
{
WifiTrack *track = (WifiTrack *)song;
return track->size;
}
int TemplateDevice::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
)
{
WifiTrack *track = (WifiTrack *)song;
char download_url[1024] = {0};
StringCbPrintfA(download_url, sizeof(download_url), "%s/file/%S", url, track->id);
HANDLE event = CreateEvent(0, FALSE, FALSE, 0);
if (!_wcsicmp(track->mime_type, L"audio/mpeg"))
wcsncat(path, L".mp3", MAX_PATH);
else if (!_wcsicmp(track->mime_type, L"audio/mp4"))
wcsncat(path, L".m4a", MAX_PATH);
else if (!_wcsicmp(track->mime_type, L"audio/x-ms-wma"))
wcsncat(path, L".wma", MAX_PATH);
else if (!_wcsicmp(track->mime_type, L"application/ogg") || !_wcsicmp(track->mime_type, L"audio/ogg") )
wcsncat(path, L".ogg", MAX_PATH);
// TODO: more
SongDownloader *song_downloader = new SongDownloader(path, event, callback, callbackContext);
song_downloader->AddRef();
WAC_API_DOWNLOADMANAGER->DownloadEx(download_url, song_downloader, api_downloadManager::DOWNLOADEX_CALLBACK);
WaitForSingleObject(event, INFINITE);
song_downloader->Release();
return 0; // TODO: check error code
}
// art functions
void TemplateDevice::setArt(songid_t songid, void *buf, int w, int h)
{
//buf is in format ARGB32*
// TODO: implement
}
pmpart_t TemplateDevice::getArt(songid_t songid)
{
// TODO: implement
return 0;
}
void TemplateDevice::releaseArt(pmpart_t art)
{
// TODO: implement
}
int TemplateDevice::drawArt(pmpart_t art, HDC dc, int x, int y, int w, int h)
{
// TODO: implement
return 0;
}
void TemplateDevice::getArtNaturalSize(pmpart_t art, int *w, int *h)
{
// TODO: implement
}
void TemplateDevice::setArtNaturalSize(pmpart_t art, int w, int h)
{
// TODO: implement
}
void TemplateDevice::getArtData(pmpart_t art, void* data)
{
// data ARGB32* is at natural size
// TODO: implement
}
bool TemplateDevice::artIsEqual(pmpart_t a, pmpart_t b)
{
// TODO: implement
return false;
}

View File

@ -0,0 +1,127 @@
#pragma once
#include "../../Library/ml_pmp/pmp.h"
#include "../../Library/ml_pmp/transcoder.h"
#include <vector>
#include "WifiDevice.h"
#include "WifiPlaylist.h"
#include "main.h"
#include <bfc/platform/types.h>
class WifiDevice;
class TemplateDevice : public Device
{
public:
typedef std::vector<WifiTrack*> TrackList;
typedef std::vector<WifiPlaylist*> PlaylistsList;
TemplateDevice(WifiDevice *device, const char *root_url, DeviceInfo *device_info, TemplateDevice::TrackList *track_list, TemplateDevice::PlaylistsList *playlists_list);
~TemplateDevice();
virtual __int64 getDeviceCapacityAvailable(); // in bytes
virtual __int64 getDeviceCapacityTotal(); // in bytes
virtual void Eject(); // if you ejected successfully, you MUST call PMP_IPC_DEVICEDISCONNECTED and delete this;
virtual void Close(); // save any changes, and call PMP_IPC_DEVICEDISCONNECTED AND delete this;
void CloseAsync();
// return 0 for success, -1 for failed or cancelled
virtual int transferTrackToDevice(const itemRecordW * track, // the track to transfer
void * callbackContext, //pass this to the callback
void (*callback)(void *callbackContext, wchar_t *status), // call this every so often so the GUI can be updated. Including when finished!
songid_t * songid, // fill in the songid when you are finished
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
);
virtual int trackAddedToTransferQueue(const itemRecordW *track); // return 0 to accept, -1 for "not enough space", -2 for "incorrect format"
virtual void trackRemovedFromTransferQueue(const itemRecordW *track);
// return the amount of space that will be taken up on the device by the track (once it has been tranferred)
// or 0 for incompatable. This is usually the filesize, unless you are transcoding. An estimate is acceptable.
virtual __int64 getTrackSizeOnDevice(const itemRecordW *track);
virtual void deleteTrack(songid_t songid); // physically remove from device. Be sure to remove it from all the playlists!
virtual void commitChanges(); // optional. Will be called at a good time to save changes
virtual int getPlaylistCount(); // always at least 1. playlistnumber 0 is the Master Playlist containing all tracks.
// PlaylistName(0) should return the name of the device.
virtual void getPlaylistName(int playlistnumber, wchar_t *buf, int len);
virtual int getPlaylistLength(int playlistnumber);
virtual songid_t getPlaylistTrack(int playlistnumber,int songnum); // returns a songid
virtual void setPlaylistName(int playlistnumber, const wchar_t *buf); // with playlistnumber==0, set the name of the device.
virtual void playlistSwapItems(int playlistnumber, int posA, int posB); // swap the songs at position posA and posB
virtual void sortPlaylist(int playlistnumber, int sortBy);
virtual void addTrackToPlaylist(int playlistnumber, songid_t songid); // adds songid to the end of the playlist
virtual void removeTrackFromPlaylist(int playlistnumber, int songnum); //where songnum is the position of the track in the playlist
virtual void deletePlaylist(int playlistnumber);
virtual int newPlaylist(const wchar_t *name); // create empty playlist, returns playlistnumber. -1 for failed.
virtual void getTrackArtist(songid_t songid, wchar_t *buf, int len);
virtual void getTrackAlbum(songid_t songid, wchar_t *buf, int len);
virtual void getTrackTitle(songid_t songid, wchar_t *buf, int len);
virtual int getTrackTrackNum(songid_t songid);
virtual int getTrackDiscNum(songid_t songid);
virtual void getTrackGenre(songid_t songid, wchar_t * buf, int len);
virtual int getTrackYear(songid_t songid);
virtual __int64 getTrackSize(songid_t songid); // in bytes
virtual int getTrackLength(songid_t songid); // in millisecs
virtual int getTrackBitrate(songid_t songid); // in kbps
virtual int getTrackPlayCount(songid_t songid);
virtual int getTrackRating(songid_t songid); //0-5
virtual __time64_t getTrackLastPlayed(songid_t songid); // in unix time format
virtual __time64_t getTrackLastUpdated(songid_t songid); // in unix time format
virtual void getTrackAlbumArtist(songid_t songid, wchar_t *buf, int len);
virtual void getTrackPublisher(songid_t songid, wchar_t *buf, int len);
virtual void getTrackComposer(songid_t songid, wchar_t *buf, int len);
virtual int getTrackType(songid_t songid);
virtual void getTrackExtraInfo(songid_t songid, const wchar_t *field, wchar_t *buf, int len) ; //optional
// feel free to ignore any you don't support
virtual void setTrackArtist(songid_t songid, const wchar_t *value);
virtual void setTrackAlbum(songid_t songid, const wchar_t *value);
virtual void setTrackTitle(songid_t songid, const wchar_t *value);
virtual void setTrackTrackNum(songid_t songid, int value);
virtual void setTrackDiscNum(songid_t songid, int value);
virtual void setTrackGenre(songid_t songid, const wchar_t *value);
virtual void setTrackYear(songid_t songid, int year);
virtual void setTrackPlayCount(songid_t songid, int value);
virtual void setTrackRating(songid_t songid, int value);
virtual void setTrackLastPlayed(songid_t songid, __time64_t value); // in unix time format
virtual void setTrackLastUpdated(songid_t songid, __time64_t value); // in unix time format
virtual void setTrackAlbumArtist(songid_t songid, const wchar_t *value);
virtual void setTrackPublisher(songid_t songid, const wchar_t *value);
virtual void setTrackComposer(songid_t songid, const wchar_t *value);
virtual void setTrackExtraInfo(songid_t songid, const wchar_t *field, const wchar_t *value) ; //optional
virtual bool playTracks(songid_t * songidList, int listLength, int startPlaybackAt, bool enqueue); // return false if unsupported
virtual intptr_t extraActions(intptr_t param1, intptr_t param2, intptr_t param3,intptr_t param4);
virtual bool copyToHardDriveSupported();
virtual __int64 songSizeOnHardDrive(songid_t song); // how big a song will be when copied back. Return -1 for not supported.
virtual int copyToHardDrive(songid_t song, // the song to copy
wchar_t * path, // path to copy to, in the form "c:\directory\song". The directory will already be created, you must append ".mp3" or whatever to this string! (there is space for at least 10 new characters).
void * callbackContext, //pass this to the callback
void (*callback)(void * callbackContext, wchar_t * status), // call this every so often so the GUI can be updated. Including when finished!
int * killswitch // if this gets set to anything other than zero, the transfer has been cancelled by the user
); // -1 for failed/not supported. 0 for success.
// art functions
virtual void setArt(songid_t songid, void *buf, int w, int h); //buf is in format ARGB32*
virtual pmpart_t getArt(songid_t songid);
virtual void releaseArt(pmpart_t art);
virtual int drawArt(pmpart_t art, HDC dc, int x, int y, int w, int h);
virtual void getArtNaturalSize(pmpart_t art, int *w, int *h);
virtual void setArtNaturalSize(pmpart_t art, int w, int h);
virtual void getArtData(pmpart_t art, void* data); // data ARGB32* is at natural size
virtual bool artIsEqual(pmpart_t a, pmpart_t b);
PlaylistsList playlists;
TrackList tracks;
DeviceInfo device_info;
char *url;
int image16, image160;
Transcoder *transcoder;
int64_t transferQueueLength;
};

View File

@ -0,0 +1,72 @@
#include "main.h"
#include "images.h"
#include "resource.h"
#include <strsafe.h>
static int small_images[] = { IDB_GENERIC_16, IDB_EVO_16, IDB_INCREDIBLE_16, IDB_NEXUSONE_16, IDB_DROID_16 };
static int large_images[] = { IDB_GENERIC_160, IDB_EVO_160, IDB_INCREDIBLE_160, IDB_NEXUSONE_160, IDB_DROID_160 };
int GetImageIndex(const wchar_t *manufacturer, const wchar_t *model)
{
if (!wcscmp(manufacturer, L"HTC"))
{
if (!wcscmp(model, L"PC36100")) // evo
{
return 1;
}
else if (!wcscmp(model, L"ADR6300")) // incredible
{
return 2;
}
else if (!wcscmp(model, L"Nexus One"))
{
return 3;
}
}
else if (!wcscmp(manufacturer, L"motorola"))
{
if (!wcscmp(model, L"DROID2"))
{
return 4;
}
}
return 0;
}
void GetImagePath(int image_index, int width, int height, wchar_t *path, size_t path_cch)
{
if (image_index < 0)
{
path[0]=0;
return;
}
if (width <= 16 && height <= 16)
{
if (image_index >= sizeof(small_images)/sizeof(small_images[0]))
{
path[0]=0;
return;
}
int resource = small_images[image_index];
FormatResProtocol(MAKEINTRESOURCE(resource), L"PNG", path, path_cch);
}
else
{
if (image_index >= sizeof(large_images)/sizeof(large_images[0]))
{
path[0]=0;
return;
}
int resource = large_images[image_index];
FormatResProtocol(MAKEINTRESOURCE(resource), L"PNG", path, path_cch);
}
}
int GetSmallImageID(int image_index)
{
if (image_index < 0 || image_index >= sizeof(small_images)/sizeof(small_images[0]))
return IDB_GENERIC_16;
return small_images[image_index];
}

View File

@ -0,0 +1,5 @@
#pragma once
int GetImageIndex(const wchar_t *manufacturer, const wchar_t *model);
void GetImagePath(int image_index, int width, int height, wchar_t *path, size_t path_cch);
int GetSmallImageID(int image_index);

View File

@ -0,0 +1,263 @@
#include "../../Library/ml_pmp/pmp.h"
#include "../Winamp/wa_ipc.h"
#include "device.h"
#include "api.h"
#include "main.h"
#include "nu/ns_wc.h"
#include "resource.h"
#include <shlwapi.h>
#include <strsafe.h>
#define PLUGIN_VERSION L"1.56"
int winampVersion = 0;
ifc_devicesupportedcommandenum *command_enum=0;
ifc_devicesupportedcommandstore *command_store=0;
ifc_deviceeventmanager *device_event_manager;
char winamp_name[260] = {0};
char winamp_id_str[40] = {0};
wchar_t inifile[MAX_PATH] = {0};
GUID winamp_id = GUID_NULL;
static int Init();
static void Quit();
static intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3);
PMPDevicePlugin plugin = {PMPHDR_VER,0,Init,Quit,MessageProc};
void StartListenServer();
BOOL FormatResProtocol(const wchar_t *resourceName, const wchar_t *resourceType, wchar_t *buffer, size_t bufferMax)
{
unsigned long filenameLength;
if (NULL == resourceName)
return FALSE;
if (FAILED(StringCchCopyExW(buffer, bufferMax, L"res://", &buffer, &bufferMax, 0)))
return FALSE;
filenameLength = GetModuleFileNameW(plugin.hDllInstance, buffer, (DWORD)bufferMax);
if (0 == filenameLength || bufferMax == filenameLength)
return FALSE;
buffer += filenameLength;
bufferMax -= filenameLength;
if (NULL != resourceType)
{
if (FALSE != IS_INTRESOURCE(resourceType))
{
if (FAILED(StringCchPrintfExW(buffer, bufferMax, &buffer, &bufferMax, 0, L"/#%d", (int)(INT_PTR)resourceType)))
return FALSE;
}
else
{
if (FAILED(StringCchPrintfExW(buffer, bufferMax, &buffer, &bufferMax, 0, L"/%s", resourceType)))
return FALSE;
}
}
if (FALSE != IS_INTRESOURCE(resourceName))
{
if (FAILED(StringCchPrintfExW(buffer, bufferMax, &buffer, &bufferMax, 0, L"/#%d", (int)(INT_PTR)resourceName)))
return FALSE;
}
else
{
if (FAILED(StringCchPrintfExW(buffer, bufferMax, &buffer, &bufferMax, 0, L"/%s", resourceName)))
return FALSE;
}
return TRUE;
}
class WifiDeviceConnection : public ifc_deviceconnection
{
public:
WifiDeviceConnection()
{
}
const char *GetName()
{
return "wifi";
}
HRESULT GetIcon(wchar_t *buffer, size_t bufferMax, int width, int height)
{
if(FALSE == FormatResProtocol(MAKEINTRESOURCE(IDB_WIFI), L"PNG", buffer, bufferMax))
return E_FAIL;
return S_OK;
}
HRESULT GetDisplayName(wchar_t *buffer, size_t bufferMax)
{
if (NULL == buffer)
return E_POINTER;
WASABI_API_LNGSTRINGW_BUF(IDS_DEVICE_CONNECTION_WIFI, buffer, bufferMax);
return S_OK;
}
protected:
#define CBCLASS WifiDeviceConnection
START_DISPATCH_INLINE;
CB(API_GETNAME, GetName);
CB(API_GETICON, GetIcon);
CB(API_GETDISPLAYNAME, GetDisplayName);
END_DISPATCH;
#undef CBCLASS
};
class AttachCommand : public ifc_devicecommand
{
public:
const char *GetName()
{
return "attach";
}
HRESULT GetIcon(wchar_t *buffer, size_t bufferMax, int width, int height)
{
int resourceId;
if (width <= 16 && height <= 16)
resourceId = IDB_ATTACH_16;
else
resourceId = IDB_ATTACH;
if(FALSE == FormatResProtocol(MAKEINTRESOURCE(resourceId), L"PNG", buffer, bufferMax))
return E_FAIL;
return S_OK;
}
HRESULT GetDisplayName(wchar_t *buffer, size_t bufferMax)
{
if (NULL == buffer)
return E_POINTER;
WASABI_API_LNGSTRINGW_BUF(IDS_DEVICE_CMD_ATTACH, buffer, bufferMax);
return S_OK;
}
HRESULT GetDescription(wchar_t *buffer, size_t bufferMax)
{
if (NULL == buffer)
return E_POINTER;
WASABI_API_LNGSTRINGW_BUF(IDS_DEVICE_CMD_ATTACH_DESC, buffer, bufferMax);
return S_OK;
}
#define CBCLASS AttachCommand
START_DISPATCH_INLINE;
CB(API_GETNAME, GetName);
CB(API_GETICON, GetIcon);
CB(API_GETDISPLAYNAME, GetDisplayName);
CB(API_GETDESCRIPTION, GetDescription);
END_DISPATCH;
#undef CBCLASS
};
class DeviceCommand : public Countable<ifc_devicesupportedcommand>
{
public:
DeviceCommand(const char *name, DeviceCommandFlags flags);
public:
const char *GetName();
HRESULT GetFlags(DeviceCommandFlags *flags);
REFERENCE_COUNT_IMPLEMENTATION;
public:
const char *name;
DeviceCommandFlags flags;
RECVS_DISPATCH;
};
static AttachCommand attach_command;
static WifiDeviceConnection wifi_connection;
static int Init()
{
winampVersion = (int)SendMessage(plugin.hwndWinampParent, WM_WA_IPC, 0, IPC_GETVERSION);
WasabiInit();
if (!AGAVE_API_DEVICEMANAGER)
return 1;
WASABI_API_APP->GetUserID(&winamp_id);
StringCbPrintfA(winamp_id_str, sizeof(winamp_id_str), "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", (int)winamp_id.Data1, (int)winamp_id.Data2, (int)winamp_id.Data3, (int)winamp_id.Data4[0], (int)winamp_id.Data4[1], (int)winamp_id.Data4[2], (int)winamp_id.Data4[3], (int)winamp_id.Data4[4], (int)winamp_id.Data4[5], (int)winamp_id.Data4[6], (int)winamp_id.Data4[7] );
wchar_t user_name[128] = {0};
wchar_t computer_name[128] = {0};
DWORD buffer_size_user = 128, buffer_size_computer=128;
if (GetUserNameW(user_name, &buffer_size_user) && GetComputerNameW(computer_name, &buffer_size_computer))
{
wchar_t winamp_name_utf16[260] = {0};
StringCbPrintfW(winamp_name_utf16, sizeof(winamp_name_utf16), L"%s (%s)", user_name, computer_name);
WideCharToMultiByteSZ(CP_UTF8, 0, winamp_name_utf16, -1, winamp_name, sizeof(winamp_name), 0, 0);
}
else
StringCbCopyA(winamp_name, sizeof(winamp_name), "Winamp");
const wchar_t *settings_path = WASABI_API_APP->path_getUserSettingsPath();
PathCombineW(inifile, settings_path, L"Plugins\\ml\\pmp_wifi.ini");
// need to have this initialized before we try to do anything with localization features
WASABI_API_START_LANG(plugin.hDllInstance,PmpWifiLangGUID);
static wchar_t szDescription[256];
StringCbPrintfW(szDescription, sizeof(szDescription),
WASABI_API_LNGSTRINGW(IDS_NULLSOFT_WIFI_DEVICE_PLUGIN), PLUGIN_VERSION);
plugin.description = szDescription;
if (AGAVE_API_DEVICEMANAGER)
{
ifc_devicecommand *command = &attach_command;
AGAVE_API_DEVICEMANAGER->CommandRegister(&command, 1);
ifc_deviceconnection *connection = &wifi_connection;
AGAVE_API_DEVICEMANAGER->ConnectionRegister(&connection, 1);
AGAVE_API_DEVICEMANAGER->CreateSupportedCommandStore(&command_store);
command_store->Add("attach", DeviceCommandFlag_Primary);
AGAVE_API_DEVICEMANAGER->CreateDeviceEventManager(&device_event_manager);
}
//AGAVE_API_DEVICEMANAGER->CreateSupportedCommandEnum(&command, 1, &command_enum);
/* TODO: Use this if your device shows up as a normal drive
SendMessage(plugin.hwndPortablesParent,WM_PMP_IPC,(WPARAM)autoDetectCallback,PMP_IPC_ENUM_ACTIVE_DRIVES);
*/
StartListenServer();
return 0;
}
static void Quit()
{
StopListenServer();
WasabiQuit();
}
static intptr_t MessageProc(int msg, intptr_t param1, intptr_t param2, intptr_t param3)
{
switch(msg) {
case PMP_DEVICECHANGE:
// TODO: Implement
return 0;
case PMP_NO_CONFIG:
return TRUE;
case PMP_CONFIG:
// TODO: Implement (Egg: changed from 1 to 0, for now)
return 0;
}
return 0;
}
extern "C" __declspec(dllexport) PMPDevicePlugin *winampGetPMPDevicePlugin()
{
return &plugin;
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "../../Library/ml_pmp/pmp.h"
#include "../Winamp/wa_ipc.h"
#include <bfc/platform/types.h>
#include "modelInfo.h"
extern PMPDevicePlugin plugin;
extern int winampVersion;
extern GUID winamp_id;
extern char winamp_id_str[40];
extern char winamp_name[260];
extern wchar_t inifile[MAX_PATH];
void StopListenServer();
BOOL FormatResProtocol(const wchar_t *resourceName, const wchar_t *resourceType, wchar_t *buffer, size_t bufferMax);
// result from <device> XML data structure
struct DeviceInfo
{
uint64_t total_space, used_space;
uint64_t id;
wchar_t manufacturer[128];
wchar_t model[128];
wchar_t name[128];
wchar_t product[128];
const ModelInfo *modelInfo;
};
extern "C" void DeviceInfo_Init(DeviceInfo *device_info);
extern "C" void DeviceInfo_Copy(DeviceInfo *dest, const DeviceInfo *source);

View File

@ -0,0 +1,168 @@
#include "main.h"
#include "./modelInfo.h"
#include "./api.h"
#include "./resource.h"
#include <strsafe.h>
typedef struct ManufacturerInfo
{
const wchar_t *name;
const ModelInfo *records;
size_t count;
} ManufacturerInfo;
#define MANUFACTURER(_name, _model_table)\
{ (_name), (_model_table), ARRAYSIZE(_model_table) }
#define MODEL(_name, _title_res_id, _small_icon_res_id, _large_icon_res_id)\
{ (_name), MAKEINTRESOURCE(_title_res_id), MAKEINTRESOURCE(_small_icon_res_id), MAKEINTRESOURCE(_large_icon_res_id)}
const struct ModelInfo HtcModelTable[] =
{
MODEL(L"PC36100", IDS_DEVICE_MODEL_HTC_EVO, IDB_EVO_16, IDB_EVO_160),
MODEL(L"ADR6300", IDS_DEVICE_MODEL_HTC_INCREDIBLE, IDB_INCREDIBLE_16, IDB_INCREDIBLE_160),
MODEL(L"Nexus One", IDS_DEVICE_MODEL_HTC_NEXUS_ONE, IDB_NEXUSONE_16, IDB_NEXUSONE_160),
MODEL(L"Desire", IDS_DEVICE_MODEL_HTC_DESIRE, IDB_HTC_DESIRE_16, IDB_HTC_DESIRE_160),
MODEL(L"Wildfire", IDS_DEVICE_MODEL_HTC_WILDFIRE, 0, 0),
MODEL(L"Hero", IDS_DEVICE_MODEL_HTC_HERO, 0, 0),
};
const struct ModelInfo MotorolaModelTable[] =
{
MODEL(L"Droid", IDS_DEVICE_MODEL_MOTOROLA_DROID, IDB_DROID_16, IDB_DROID_160),
MODEL(L"DROID2", IDS_DEVICE_MODEL_MOTOROLA_DROID2, IDB_DROID_16, IDB_DROID_160),
MODEL(L"DROIDX", IDS_DEVICE_MODEL_MOTOROLA_DROIDX, IDB_DROIDX_16, IDB_DROIDX_160),
MODEL(L"Milestone", IDS_DEVICE_MODEL_MOTOROLA_MILESTONE, IDB_DROID_16, IDB_DROID_160),
MODEL(L"DROIDX2", IDS_DEVICE_MODEL_MOTOROLA_DROIDX2, IDB_DROID_16, IDB_DROID_160),
};
const struct ModelInfo SamsungModelTable[] =
{
MODEL(L"GT I9000", IDS_DEVICE_MODEL_SAMSUNG_GALAXY_S, 0, 0),
};
const static ManufacturerInfo ManufacturerTable[] =
{
MANUFACTURER(L"HTC", HtcModelTable),
MANUFACTURER(L"motorola", MotorolaModelTable),
MANUFACTURER(L"samsung", SamsungModelTable),
};
const static ModelInfo defaultModel = { L"", L"", MAKEINTRESOURCE(IDB_GENERIC_16), MAKEINTRESOURCE(IDB_GENERIC_160)};
const ModelInfo *
FindModelInfo(const wchar_t *manufacturer, const wchar_t *model, BOOL allowDefault)
{
if (NULL != manufacturer &&
NULL != model)
{
const ManufacturerInfo *manufacturerInfo;
size_t i;
unsigned long lcid;
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
for (i = 0; i < ARRAYSIZE(ManufacturerTable); i++)
{
manufacturerInfo = &ManufacturerTable[i];
if (CSTR_EQUAL == CompareString(lcid, NORM_IGNORECASE, manufacturerInfo->name, -1, manufacturer, -1))
{
for (i = 0; i < manufacturerInfo->count; i++)
{
const ModelInfo *modelInfo = &manufacturerInfo->records[i];
if (CSTR_EQUAL == CompareString(lcid, NORM_IGNORECASE, modelInfo->name, -1, model, -1))
{
return modelInfo;
}
}
break;
}
}
}
if (FALSE != allowDefault)
return &defaultModel;
return NULL;
}
const ModelInfo*
GetDefaultModelInfo()
{
return &defaultModel;
}
HRESULT ModelInfo_CopyDisplayName(const ModelInfo *modelInfo, wchar_t *buffer, size_t bufferMax)
{
if (NULL == modelInfo)
return E_INVALIDARG;
if (NULL == buffer)
return E_POINTER;
if (NULL == modelInfo->displayName)
return E_UNEXPECTED;
if (FALSE != IS_INTRESOURCE(modelInfo->displayName))
{
WASABI_API_LNGSTRINGW_BUF((int)(intptr_t)modelInfo->displayName, buffer, bufferMax);
return S_OK;
}
if (FAILED(StringCchCopy(buffer, bufferMax, modelInfo->displayName)))
return E_FAIL;
return S_OK;
}
const wchar_t *ModelInfo_GetIconName(const ModelInfo *modelInfo, int width, int height, BOOL allowDefault)
{
if (NULL == modelInfo)
{
if (FALSE == allowDefault)
return NULL;
modelInfo = GetDefaultModelInfo();
if (NULL == modelInfo)
return NULL;
}
if (width <= 16 && height <= 16)
{
if (NULL == modelInfo->smallIcon &&
FALSE != allowDefault)
{
modelInfo = GetDefaultModelInfo();
if (NULL == modelInfo)
return NULL;
}
return modelInfo->smallIcon;
}
if (NULL == modelInfo->largeIcon &&
FALSE != allowDefault)
{
modelInfo = GetDefaultModelInfo();
if (NULL == modelInfo)
return NULL;
}
return modelInfo->largeIcon;
}
HRESULT ModelInfo_GetIconPath(const ModelInfo *modelInfo, int width, int height, wchar_t *buffer, size_t bufferMax, BOOL allowDefault)
{
const wchar_t *iconName;
iconName = ModelInfo_GetIconName(modelInfo, width, height, allowDefault);
if (NULL == iconName)
return E_FAIL;
if (FALSE == FormatResProtocol(iconName, L"PNG", buffer, bufferMax))
return E_FAIL;
return S_OK;
}

View File

@ -0,0 +1,22 @@
#pragma once
typedef struct ModelInfo
{
const wchar_t *name;
const wchar_t *displayName;
const wchar_t *smallIcon;
const wchar_t *largeIcon;
} ModelInfo;
const ModelInfo *GetDefaultModelInfo();
const ModelInfo *FindModelInfo(const wchar_t *manufacturer, const wchar_t *model, BOOL allowDefault);
/* helpers*/
HRESULT ModelInfo_CopyDisplayName(const ModelInfo *modelInfo, wchar_t *buffer, size_t bufferMax);
const wchar_t *ModelInfo_GetIconName(const ModelInfo *modelInfo, int width, int height, BOOL allowDefault);
HRESULT ModelInfo_GetIconPath(const ModelInfo *modelInfo, int width, int height, wchar_t *buffer, size_t bufferMax, BOOL allowDefault);

View File

@ -0,0 +1,126 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#include ""version.rc2""\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// PNG
//
IDB_GENERIC_16 PNG "resources\\generic_drive_wifi_16.png"
IDB_HTC_DESIRE_16 PNG "resources\\htc_desire_passion_bravo_16.png"
IDB_EVO_16 PNG "resources\\htc_evo_4g_16.png"
IDB_NEXUSONE_16 PNG "resources\\htc_nexus_one_16.png"
IDB_DROID_16 PNG "resources\\motorola_droid_16.png"
IDB_GENERIC_160 PNG "resources\\generic_android.png"
IDB_HTC_DESIRE_160 PNG "resources\\htc_desire_passion_bravo.png"
IDB_EVO_160 PNG "resources\\htc_evo_4g.png"
IDB_DROID_160 PNG "resources\\motorola_droid.png"
IDB_WIFI PNG "resources\\wifi.png"
IDB_ATTACH PNG "resources\\attach.png"
IDB_ATTACH_16 PNG "resources\\attach16.png"
IDB_INCREDIBLE_160 PNG "resources\\htc_incredible.png"
IDB_INCREDIBLE_16 PNG "resources\\htc_incredible_16.png"
IDB_NEXUSONE_160 PNG "resources\\nexus_one.png"
IDB_DROIDX_160 PNG "resources\\motorola_droid_x.png"
IDB_DROIDX_16 PNG "resources\\motorola_droid_x_16.png"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_NULLSOFT_WIFI_DEVICE_PLUGIN "Nullsoft Wi-Fi Device Plug-in v%s"
65535 "{3066887B-CA40-4683-897F-4416FE349D7E}"
END
STRINGTABLE
BEGIN
IDS_ACTIVITY_CONNECT "Connecting..."
IDS_ACTIVITY_CONNECT_DESC "Connecting device."
IDS_DEVICE_CONNECTION_WIFI "Wi-Fi"
IDS_DEVICE_CMD_ATTACH "&Attach"
IDS_DEVICE_CMD_ATTACH_DESC "Attach device to Winamp"
IDS_DEVICE_MODEL_HTC_EVO "HTC Evo 4G"
IDS_DEVICE_MODEL_HTC_INCREDIBLE "DROID INCREDIBLE by HTC"
IDS_DEVICE_MODEL_HTC_NEXUS_ONE "Google Nexus One"
IDS_DEVICE_MODEL_MOTOROLA_DROID2 "DROID 2 by Motorola"
IDS_DEVICE_MODEL_MOTOROLA_DROIDX "DROID X by Motorola"
END
STRINGTABLE
BEGIN
IDS_DEVICE_MODEL_MOTOROLA_DROID "DROID by Motorola"
IDS_DEVICE_MODEL_HTC_DESIRE "HTC Desire"
IDS_DEVICE_MODEL_SAMSUNG_GALAXY_S "Samsung Galaxy S"
IDS_DEVICE_MODEL_MOTOROLA_MILESTONE "Motorola Milestone"
IDS_DEVICE_MODEL_HTC_WILDFIRE "HTC Wildfire"
IDS_DEVICE_MODEL_HTC_HERO "HTC Hero"
IDS_CONNECTING "Connecting"
IDS_UPLOADING "Uploading (%d%%)"
IDS_COMPLETED "Completed"
IDS_DEVICE_MODEL_MOTOROLA_DROIDX2 "DROID X2 by Motorola"
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#include "version.rc2"
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -0,0 +1,83 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29509.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pmp_wifi", "pmp_wifi.vcxproj", "{DD76E337-88AD-402E-ACC7-E33510A5AE43}"
ProjectSection(ProjectDependencies) = postProject
{57C90706-B25D-4ACA-9B33-95CDB2427C27} = {57C90706-B25D-4ACA-9B33-95CDB2427C27}
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11} = {44AEBB50-1331-4F2E-8AEC-56C82DE16C11}
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915} = {F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}
{E105A0A2-7391-47C5-86AC-718003524C3D} = {E105A0A2-7391-47C5-86AC-718003524C3D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nx", "..\replicant\nx\nx.vcxproj", "{57C90706-B25D-4ACA-9B33-95CDB2427C27}"
ProjectSection(ProjectDependencies) = postProject
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11} = {44AEBB50-1331-4F2E-8AEC-56C82DE16C11}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nu", "..\replicant\nu\nu.vcxproj", "{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnetlib", "..\replicant\jnetlib\jnetlib.vcxproj", "{E105A0A2-7391-47C5-86AC-718003524C3D}"
ProjectSection(ProjectDependencies) = postProject
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11} = {44AEBB50-1331-4F2E-8AEC-56C82DE16C11}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "..\replicant\zlib\zlib.vcxproj", "{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}"
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
{DD76E337-88AD-402E-ACC7-E33510A5AE43}.Debug|Win32.ActiveCfg = Debug|Win32
{DD76E337-88AD-402E-ACC7-E33510A5AE43}.Debug|Win32.Build.0 = Debug|Win32
{DD76E337-88AD-402E-ACC7-E33510A5AE43}.Debug|x64.ActiveCfg = Debug|x64
{DD76E337-88AD-402E-ACC7-E33510A5AE43}.Debug|x64.Build.0 = Debug|x64
{DD76E337-88AD-402E-ACC7-E33510A5AE43}.Release|Win32.ActiveCfg = Release|Win32
{DD76E337-88AD-402E-ACC7-E33510A5AE43}.Release|Win32.Build.0 = Release|Win32
{DD76E337-88AD-402E-ACC7-E33510A5AE43}.Release|x64.ActiveCfg = Release|x64
{DD76E337-88AD-402E-ACC7-E33510A5AE43}.Release|x64.Build.0 = Release|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.ActiveCfg = Debug|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|Win32.Build.0 = Debug|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.ActiveCfg = Debug|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Debug|x64.Build.0 = Debug|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.ActiveCfg = Release|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|Win32.Build.0 = Release|Win32
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.ActiveCfg = Release|x64
{57C90706-B25D-4ACA-9B33-95CDB2427C27}.Release|x64.Build.0 = Release|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.ActiveCfg = Debug|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|Win32.Build.0 = Debug|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.ActiveCfg = Debug|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Debug|x64.Build.0 = Debug|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.ActiveCfg = Release|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|Win32.Build.0 = Release|Win32
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.ActiveCfg = Release|x64
{F1F5CD60-0D5B-4CEA-9EEB-2F87FF9AA915}.Release|x64.Build.0 = Release|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.ActiveCfg = Debug|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|Win32.Build.0 = Debug|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.ActiveCfg = Debug|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Debug|x64.Build.0 = Debug|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.ActiveCfg = Release|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|Win32.Build.0 = Release|Win32
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.ActiveCfg = Release|x64
{E105A0A2-7391-47C5-86AC-718003524C3D}.Release|x64.Build.0 = Release|x64
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}.Debug|Win32.ActiveCfg = Debug|Win32
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}.Debug|Win32.Build.0 = Debug|Win32
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}.Debug|x64.ActiveCfg = Debug|x64
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}.Debug|x64.Build.0 = Debug|x64
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}.Release|Win32.ActiveCfg = Release|Win32
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}.Release|Win32.Build.0 = Release|Win32
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}.Release|x64.ActiveCfg = Release|x64
{44AEBB50-1331-4F2E-8AEC-56C82DE16C11}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C4E799C1-027B-487B-8E1A-31F2D26A1AFE}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,341 @@
<?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>{DD76E337-88AD-402E-ACC7-E33510A5AE43}</ProjectGuid>
<RootNamespace>pmp_wifi</RootNamespace>
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
<LibraryPath>$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(PlatformShortName)_$(Configuration)\</OutDir>
<IntDir>$(PlatformShortName)_$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Label="Vcpkg">
<VcpkgEnableManifest>false</VcpkgEnableManifest>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
<VcpkgConfiguration>Debug</VcpkgConfiguration>
</PropertyGroup>
<PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<VcpkgInstalledDir>
</VcpkgInstalledDir>
<VcpkgUseStatic>false</VcpkgUseStatic>
<VcpkgTriplet>x86-windows-static-md</VcpkgTriplet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\Wasabi;..\..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;pmp_wifi_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<DelayLoadDLLs>nxlite.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<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\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\..\Wasabi;..\..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;_DEBUG;_WINDOWS;_USRDLL;pmp_wifi_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<DelayLoadDLLs>nxlite.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<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\
xcopy /Y /D $(IntDir)$(TargetName).pdb ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\Wasabi;..\..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;pmp_wifi_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>None</DebugInformationFormat>
<DisableSpecificWarnings>4018;4995;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<DelayLoadDLLs>nxlite.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<Optimization>MinSpace</Optimization>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalIncludeDirectories>..\..\..\Wasabi;..\..\..\replicant;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN64;NDEBUG;_WINDOWS;_USRDLL;pmp_wifi_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4018;4995;4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>ws2_32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<DelayLoadDLLs>nxlite.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
<GenerateDebugInformation>false</GenerateDebugInformation>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
<PostBuildEvent>
<Command>xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\ </Command>
<Message>Post build event: 'xcopy /Y /D $(OutDir)$(TargetName)$(TargetExt) ..\..\..\..\Build\Winamp_$(PlatformShortName)_$(Configuration)\Plugins\'</Message>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\..\replicant\jnetlib\asyncdns.cpp" />
<ClCompile Include="..\..\..\replicant\jnetlib\multicastlisten.cpp" />
<ClCompile Include="..\..\..\replicant\jnetlib\udpconnection.cpp" />
<ClCompile Include="..\..\..\replicant\jnetlib\util.cpp" />
<ClCompile Include="..\..\..\replicant\nu\RingBuffer.cpp" />
<ClCompile Include="api.cpp" />
<ClCompile Include="ConnectActivity.cpp" />
<ClCompile Include="device.cpp" />
<ClCompile Include="images.cpp" />
<ClCompile Include="InfoDownloader.cpp" />
<ClCompile Include="ListenServer.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="modelInfo.cpp" />
<ClCompile Include="Pair.cpp" />
<ClCompile Include="PlaylistSync.cpp" />
<ClCompile Include="post.cpp" />
<ClCompile Include="RenameDownloader.cpp" />
<ClCompile Include="SongDownloader.cpp" />
<ClCompile Include="SongListDownloader.cpp" />
<ClCompile Include="WifiDevice.cpp" />
<ClCompile Include="WifiPlaylist.cpp" />
<ClCompile Include="XMLString.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\replicant\jnetlib\asyncdns.h" />
<ClInclude Include="..\..\..\replicant\jnetlib\multicastlisten.h" />
<ClInclude Include="..\..\..\replicant\jnetlib\udpconnection.h" />
<ClInclude Include="..\..\..\replicant\jnetlib\util.h" />
<ClInclude Include="..\..\Library\ml_pmp\pmp.h" />
<ClInclude Include="..\..\..\replicant\nu\RingBuffer.h" />
<ClInclude Include="api.h" />
<ClInclude Include="ConnectActivity.h" />
<ClInclude Include="device.h" />
<ClInclude Include="InfoDownloader.h" />
<ClInclude Include="main.h" />
<ClInclude Include="modelInfo.h" />
<ClInclude Include="Pair.h" />
<ClInclude Include="PlaylistSync.h" />
<ClInclude Include="RenameDownloader.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="SongDownloader.h" />
<ClInclude Include="SongListDownloader.h" />
<ClInclude Include="WifiDevice.h" />
<ClInclude Include="WifiPlaylist.h" />
<ClInclude Include="XMLString.h" />
</ItemGroup>
<ItemGroup>
<Image Include="attach.png" />
<Image Include="attach16.png" />
<Image Include="generic_android.png" />
<Image Include="generic_drive_wifi_16.png" />
<Image Include="htc_desire_passion_bravo.png" />
<Image Include="htc_desire_passion_bravo_16.png" />
<Image Include="htc_evo_4g.png" />
<Image Include="htc_evo_4g_16.png" />
<Image Include="htc_hd2.png" />
<Image Include="htc_hd2_16.png" />
<Image Include="htc_incredible.png" />
<Image Include="htc_incredible_16.png" />
<Image Include="htc_nexus_one_16.png" />
<Image Include="motorola_droid.png" />
<Image Include="motorola_droid_16.png" />
<Image Include="motorola_droid_x.png" />
<Image Include="motorola_droid_x_16.png" />
<Image Include="nexus_one.png" />
<Image Include="wifi.png" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_wifi.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\General\gen_ml\gen_ml.vcxproj">
<Project>{9b212232-4908-49d2-8d6d-96555b1f701e}</Project>
</ProjectReference>
<ProjectReference Include="..\..\Library\ml_pmp\ml_pmp.vcxproj">
<Project>{c524f141-87ca-491b-91d8-920248c9066e}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\replicant\nu\nu.vcxproj">
<Project>{f1f5cd60-0d5b-4cea-9eeb-2f87ff9aa915}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\replicant\nx\nx.vcxproj">
<Project>{57c90706-b25d-4aca-9b33-95cdb2427c27}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\Wasabi\bfc\bfc.vcxproj">
<Project>{d0ec862e-dddd-4f4f-934f-b75dc9062dc1}</Project>
</ProjectReference>
<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>

View File

@ -0,0 +1,214 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="api.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ConnectActivity.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="device.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="images.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="InfoDownloader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ListenServer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="modelInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Pair.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XMLString.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="WifiPlaylist.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="WifiDevice.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SongListDownloader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SongDownloader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RenameDownloader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="post.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PlaylistSync.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\replicant\jnetlib\asyncdns.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\replicant\jnetlib\multicastlisten.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\replicant\nu\RingBuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\replicant\jnetlib\udpconnection.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\replicant\jnetlib\util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ConnectActivity.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="device.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="InfoDownloader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="modelInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Pair.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PlaylistSync.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RenameDownloader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SongDownloader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SongListDownloader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="WifiDevice.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="WifiPlaylist.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="XMLString.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\replicant\jnetlib\asyncdns.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\replicant\jnetlib\multicastlisten.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\Library\ml_pmp\pmp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\replicant\nu\RingBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\replicant\jnetlib\udpconnection.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\replicant\jnetlib\util.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="attach.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="attach16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="generic_android.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="generic_drive_wifi_16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_desire_passion_bravo.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_desire_passion_bravo_16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_evo_4g.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_evo_4g_16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_hd2.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_hd2_16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_incredible.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_incredible_16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="htc_nexus_one_16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="motorola_droid.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="motorola_droid_16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="motorola_droid_x.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="motorola_droid_x_16.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="nexus_one.png">
<Filter>Image Files</Filter>
</Image>
<Image Include="wifi.png">
<Filter>Image Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{0b5eaaf3-d36a-4b37-b20f-50ebc6c35a6f}</UniqueIdentifier>
</Filter>
<Filter Include="Ressource Files">
<UniqueIdentifier>{2f4cb2e1-34f6-44e9-bb88-ff40ce0f6e61}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{92dbab76-3096-4992-8074-7eabc2673267}</UniqueIdentifier>
</Filter>
<Filter Include="Image Files">
<UniqueIdentifier>{075a31ea-0a24-40e9-b4da-cc17b11a8459}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="pmp_wifi.rc">
<Filter>Ressource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,518 @@
#include "main.h"
#include "api.h"
#include "resource.h"
#include "../xml/obj_xml.h"
#include "nu/AutoChar.h"
#include "../nu/AutoUrl.h"
#include "../nu/AutoHeader.h"
#include "../../..\Components\wac_network\wac_network_http_receiver_api.h"
#include "../agave/albumart/svc_albumartprovider.h"
#include <api/service/waservicefactory.h>
#include <shlwapi.h>
#include <strsafe.h>
static const GUID internetConfigGroupGUID =
{
0xc0a565dc, 0xcfe, 0x405a, { 0xa2, 0x7c, 0x46, 0x8b, 0xc, 0x8a, 0x3a, 0x5c }
};
#define USER_AGENT_SIZE (10 /*User-Agent*/ + 2 /*: */ + 6 /*Winamp*/ + 1 /*/*/ + 1 /*5*/ + 3/*.21*/ + 1 /*Null*/)
static void SetUserAgent(api_httpreceiver *http)
{
char user_agent[USER_AGENT_SIZE] = {0};
int bigVer = ((winampVersion & 0x0000FF00) >> 12);
int smallVer = ((winampVersion & 0x000000FF));
StringCchPrintfA(user_agent, USER_AGENT_SIZE, "User-Agent: Winamp/%01x.%02x", bigVer, smallVer);
http->addheader(user_agent);
}
#define HTTP_BUFFER_SIZE 8192
#define POST_BUFFER_SIZE (128*1024)
int PostFile(const char *base_url, const wchar_t *filename, const itemRecordW *track, obj_xml *parser, int *killswitch,
void (*callback)(void *callbackContext, wchar_t *status), void *context, char *new_item_id, size_t new_item_id_len)
{
//if (!parser)
// return 1;
bool first=true;
char url[2048] = {0};
char *p_url=url;
size_t url_cch=sizeof(url)/sizeof(*url);
FILE *f = _wfopen(filename, L"rb");
if (!f)
return 1;
api_httpreceiver *http = 0;
waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
if (sf)
http = (api_httpreceiver *)sf->getInterface();
if (!http)
return 1;
int use_proxy = 1;
bool proxy80 = AGAVE_API_CONFIG->GetBool(internetConfigGroupGUID, L"proxy80", false);
if (proxy80 && strstr(url, ":") && (!strstr(url, ":80/") && strstr(url, ":80") != (url + strlen(url) - 3)))
use_proxy = 0;
const wchar_t *proxy = use_proxy?AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", 0):0;
fseek(f, 0, SEEK_END);
size_t clen = ftell(f);
size_t transferred=0;
size_t total_clen = clen;
fseek(f, 0, SEEK_SET);
http->open(API_DNS_AUTODNS, HTTP_BUFFER_SIZE, (proxy && proxy[0]) ? (const char *)AutoChar(proxy) : NULL);
http->set_sendbufsize(POST_BUFFER_SIZE);
SetUserAgent(http);
char data[POST_BUFFER_SIZE] = {0};
StringCbCopyExA(p_url, url_cch, base_url, &p_url, &url_cch, 0);
StringCbPrintfA(data, sizeof(data), "Content-Length: %u", clen);
http->addheader(data);
// http->addheader("Content-Type: application/octet-stream");
/* send metadata */
if (track->artist && track->artist[0])
{
if (first)
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?artist=%s", AutoUrl(track->artist));
else
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&artist=%s", AutoUrl(track->artist));
first=false;
}
if (track->title && track->title[0])
{
if (first)
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?title=%s", AutoUrl(track->title));
else
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&title=%s", AutoUrl(track->title));
first=false;
}
if (track->album && track->album[0])
{
if (first)
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?album=%s", AutoUrl(track->album));
else
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&album=%s", AutoUrl(track->album));
first=false;
}
if (track->composer && track->composer[0])
{
if (first)
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?composer=%s", AutoUrl(track->composer));
else
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&composer=%s", AutoUrl(track->composer));
first=false;
}
if (track->albumartist && track->albumartist[0])
{
if (first)
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?albumartist=%s", AutoUrl(track->albumartist));
else
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&albumartist=%s", AutoUrl(track->albumartist));
first=false;
}
if (track->genre && track->genre[0])
{
if (first)
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?genre=%s", AutoUrl(track->genre));
else
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&genre=%s", AutoUrl(track->genre));
first=false;
}
if (track->track > 0)
{
if (first)
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?track=%d", track->track);
else
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&track=%d", track->track);
first=false;
}
const wchar_t *ext = PathFindExtension(filename);
if (ext && ext[0])
{
if (ext[0] == '.') ext++;
if (ext[0])
{
if (first)
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "?extension=%s", AutoUrl(ext));
else
StringCbPrintfExA(p_url, url_cch, &p_url, &url_cch, 0, "&extension=%s", AutoUrl(ext));
first=false;
}
}
wchar_t mime_type[128] = {0};
if (AGAVE_API_METADATA->GetExtendedFileInfo(filename, L"mime", mime_type, 128) == 1 && mime_type[0])
{
http->AddHeaderValue("Content-Type", AutoHeader(mime_type));
}
http->AddHeaderValue("X-Winamp-ID", winamp_id_str);
http->AddHeaderValue("X-Winamp-Name", winamp_name);
http->AddHeaderValue("Expect", "100-continue");
/* connect */
callback(context, WASABI_API_LNGSTRINGW(IDS_CONNECTING));
http->connect(url, 0, "POST");
// spin and wait for a 100 response
for (;;)
{
Sleep(55);
if (*killswitch)
goto connection_failed;
int ret = http->run();
if (ret != HTTPRECEIVER_RUN_OK) // connection failed or closed
goto connection_failed;
int reply_code = http->getreplycode();
if (reply_code == 100)
break;
else if (reply_code)
goto connection_failed;
}
/* POST the data */
api_connection *connection = http->GetConnection();
if (connection)
{
if (http->run() == -1)
goto connection_failed;
while (clen)
{
int percent = MulDiv(100, (int)transferred, (int)total_clen);
wchar_t msg[128] = {0};
StringCbPrintfW(msg, sizeof(msg), WASABI_API_LNGSTRINGW(IDS_UPLOADING), percent);
callback(context, msg);
if (*killswitch)
goto connection_failed;
if (http->run() == -1)
goto connection_failed;
int connection_state = connection->get_state();
if (connection_state == CONNECTION_STATE_CLOSED || connection_state == CONNECTION_STATE_ERROR)
goto connection_failed;
size_t lengthToSend = min(clen, connection->GetSendBytesAvailable());
lengthToSend = min(lengthToSend, sizeof(data));
if (lengthToSend)
{
int bytes_read = (int)fread(data, 1, lengthToSend, f);
connection->send(data, bytes_read);
clen-=bytes_read;
transferred+=bytes_read;
}
else
{
Sleep(10);
}
}
int x;
while (x = (int)connection->GetSendBytesInQueue())
{
int connection_state = connection->get_state();
if (connection_state == CONNECTION_STATE_CLOSED || connection_state == CONNECTION_STATE_ERROR)
goto connection_failed;
Sleep(10);
if (*killswitch)
goto connection_failed;
if (http->run() == -1)
goto connection_failed;
}
}
fclose(f);
f=0;
/* retrieve reply */
int ret;
do
{
Sleep(55);
ret = http->run();
if (ret == -1) // connection failed
break;
// ---- check our reply code ----
int status = http->get_status();
switch (status)
{
case HTTPRECEIVER_STATUS_CONNECTING:
case HTTPRECEIVER_STATUS_READING_HEADERS:
break;
case HTTPRECEIVER_STATUS_READING_CONTENT:
{
const char *location = http->getheader("Location");
if (location)
StringCchCopyA(new_item_id, new_item_id_len, location);
else
new_item_id[0]=0;
sf->releaseInterface(http);
return 0;
}
break;
case HTTPRECEIVER_STATUS_ERROR:
default:
sf->releaseInterface(http);
return 1;
}
}
while (ret == HTTPRECEIVER_RUN_OK);
connection_failed:
if (f)
fclose(f);
sf->releaseInterface(http);
return 1;
}
int PostAlbumArt(const char *url, const itemRecordW *track, obj_xml *parser, int *killswitch, void (*callback)(void *callbackContext, wchar_t *status), void *context)
{
void *artData=0;
size_t datalen=0;
wchar_t *mimeType=0;
if (AGAVE_API_ALBUMART->GetAlbumArtData(track->filename, L"cover", &artData, &datalen, &mimeType) != ALBUMART_SUCCESS)
return 1;
api_httpreceiver *http = 0;
waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
if (sf)
http = (api_httpreceiver *)sf->getInterface();
if (!http)
return 1;
int use_proxy = 1;
bool proxy80 = AGAVE_API_CONFIG->GetBool(internetConfigGroupGUID, L"proxy80", false);
if (proxy80 && strstr(url, ":") && (!strstr(url, ":80/") && strstr(url, ":80") != (url + strlen(url) - 3)))
use_proxy = 0;
const wchar_t *proxy = use_proxy?AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", 0):0;
uint8_t *artDataPtr=(uint8_t *)artData;
size_t clen = datalen;
size_t transferred=0;
size_t total_clen = datalen;
http->open(API_DNS_AUTODNS, HTTP_BUFFER_SIZE, (proxy && proxy[0]) ? (const char *)AutoChar(proxy) : NULL);
http->set_sendbufsize(POST_BUFFER_SIZE);
SetUserAgent(http);
char data[POST_BUFFER_SIZE] = {0};
StringCbPrintfA(data, sizeof(data), "Content-Length: %u", datalen);
http->addheader(data);
if (mimeType)
{
StringCbPrintfA(data, sizeof(data), "Content-Type: %s", AutoHeader(mimeType));
http->addheader(data);
}
http->AddHeaderValue("X-Winamp-ID", winamp_id_str);
http->AddHeaderValue("X-Winamp-Name", winamp_name);
/* connect */
http->AddHeaderValue("Expect", "100-continue");
callback(context, WASABI_API_LNGSTRINGW(IDS_CONNECTING));
http->connect(url, 0, "POST");
// spin and wait for a 100 response
for (;;)
{
Sleep(55);
int ret = http->run();
if (ret != HTTPRECEIVER_RUN_OK) // connection failed or closed
goto connection_failed;
if (*killswitch)
goto connection_failed;
int reply_code = http->getreplycode();
if (reply_code == 100)
break;
else if (reply_code)
goto connection_failed;
}
/* POST the data */
api_connection *connection = http->GetConnection();
if (connection)
{
if (http->run() == -1)
goto connection_failed;
while (clen)
{
int percent = MulDiv(100, (int)transferred, (int)total_clen);
wchar_t msg[128] = {0};
StringCbPrintfW(msg, sizeof(msg), L"Uploading Album Art (%d%%)", percent);
callback(context, msg);
if (*killswitch)
goto connection_failed;
if (http->run() == -1)
goto connection_failed;
int connection_state = connection->get_state();
if (connection_state == CONNECTION_STATE_CLOSED || connection_state == CONNECTION_STATE_ERROR)
goto connection_failed;
size_t lengthToSend = min(clen, connection->GetSendBytesAvailable());
if (lengthToSend)
{
connection->send(artDataPtr, (int)lengthToSend);
artDataPtr += lengthToSend;
clen-=lengthToSend;
transferred+=lengthToSend;
}
else
{
Sleep(10);
}
}
int x;
while (x = (int)connection->GetSendBytesInQueue())
{
int connection_state = connection->get_state();
if (connection_state == CONNECTION_STATE_CLOSED || connection_state == CONNECTION_STATE_ERROR)
goto connection_failed;
Sleep(10);
if (*killswitch)
goto connection_failed;
if (http->run() == -1)
goto connection_failed;
}
}
/* retrieve reply */
int ret;
do
{
Sleep(55);
ret = http->run();
if (ret == -1) // connection failed
break;
// ---- check our reply code ----
int status = http->get_status();
switch (status)
{
case HTTPRECEIVER_STATUS_CONNECTING:
case HTTPRECEIVER_STATUS_READING_HEADERS:
break;
case HTTPRECEIVER_STATUS_READING_CONTENT:
{
sf->releaseInterface(http);
WASABI_API_MEMMGR->sysFree(artData);
WASABI_API_MEMMGR->sysFree(mimeType);
return 0;
}
break;
case HTTPRECEIVER_STATUS_ERROR:
default:
sf->releaseInterface(http);
WASABI_API_MEMMGR->sysFree(artData);
WASABI_API_MEMMGR->sysFree(mimeType);
return 1;
}
}
while (ret == HTTPRECEIVER_RUN_OK);
connection_failed:
WASABI_API_MEMMGR->sysFree(artData);
WASABI_API_MEMMGR->sysFree(mimeType);
sf->releaseInterface(http);
return 1;
}
int HTTP_Delete(const char *url)
{
api_httpreceiver *http = 0;
waServiceFactory *sf = plugin.service->service_getServiceByGuid(httpreceiverGUID);
if (sf)
http = (api_httpreceiver *)sf->getInterface();
if (!http)
return 1;
int use_proxy = 1;
bool proxy80 = AGAVE_API_CONFIG->GetBool(internetConfigGroupGUID, L"proxy80", false);
if (proxy80 && strstr(url, ":") && (!strstr(url, ":80/") && strstr(url, ":80") != (url + strlen(url) - 3)))
use_proxy = 0;
const wchar_t *proxy = use_proxy?AGAVE_API_CONFIG->GetString(internetConfigGroupGUID, L"proxy", 0):0;
http->open(API_DNS_AUTODNS, HTTP_BUFFER_SIZE, (proxy && proxy[0]) ? (const char *)AutoChar(proxy) : NULL);
SetUserAgent(http);
http->AddHeaderValue("X-Winamp-ID", winamp_id_str);
http->AddHeaderValue("X-Winamp-Name", winamp_name);
/* connect */
http->connect(url, 0, "DELETE");
/* retrieve reply */
int ret;
do
{
Sleep(55);
ret = http->run();
if (ret == -1) // connection failed
break;
// ---- check our reply code ----
int status = http->get_status();
switch (status)
{
case HTTPRECEIVER_STATUS_CONNECTING:
case HTTPRECEIVER_STATUS_READING_HEADERS:
break;
case HTTPRECEIVER_STATUS_READING_CONTENT:
{
sf->releaseInterface(http);
return 0;
}
break;
case HTTPRECEIVER_STATUS_ERROR:
default:
sf->releaseInterface(http);
return 1;
}
}
while (ret == HTTPRECEIVER_RUN_OK);
sf->releaseInterface(http);
return 1;
}

View File

@ -0,0 +1,65 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by pmp_wifi.rc
//
#define IDB_GENERIC_16 101
#define IDB_PNG2 102
#define IDB_HTC_DESIRE_16 102
#define IDB_PNG3 103
#define IDB_EVO16 103
#define IDB_EVO_16 103
#define IDB_PNG5 105
#define IDB_NEXUSONE_16 105
#define IDB_PNG6 106
#define IDB_DROID_16 106
#define IDB_GENERIC_160 107
#define IDB_PNG7 108
#define IDB_HTC_DESIRE_160 108
#define IDB_PNG8 109
#define IDB_EVO_160 109
#define IDB_PNG10 111
#define IDB_DROID_160 111
#define IDB_PNG1 112
#define IDB_WIFI 112
#define IDB_ATTACH 113
#define IDB_PNG11 114
#define IDB_ATTACH_16 114
#define IDB_PNG4 115
#define IDB_INCREDIBLE_160 115
#define IDB_INCREDIBLE_16 116
#define IDB_NEXUSONE_160 117
#define IDS_ACTIVITY_CONNECT 118
#define IDS_ACTIVITY_CONNECT_DESC 119
#define IDS_DEVICE_CONNECTION_WIFI 120
#define IDS_DEVICE_CMD_ATTACH 121
#define IDS_DEVICE_CMD_ATTACH_DESC 122
#define IDS_DEVICE_MODEL_HTC_EVO 123
#define IDS_DEVICE_MODEL_HTC_INCREDIBLE 124
#define IDS_DEVICE_MODEL_HTC_NEXUS_ONE 125
#define IDS_DEVICE_MODEL_MOTOROLA_DROID2 126
#define IDS_DEVICE_MODEL_MOTOROLA_DROIDX 127
#define IDS_DEVICE_MODEL_MOTOROLA_DROID 128
#define IDS_DEVICE_MODEL_HTC_DESIRE 129
#define IDS_DEVICE_MODEL_SAMSUNG_GALAXY_S 130
#define IDB_DROIDX_160 130
#define IDS_DEVICE_MODEL_MOTOROLA_MILESTONE 131
#define IDB_PNG12 131
#define IDB_DROIDX_16 131
#define IDS_DEVICE_MODEL_HTC_WILDFIRE 132
#define IDS_DEVICE_MODEL_HTC_HERO 133
#define IDS_CONNECTING 134
#define IDS_UPLOADING 135
#define IDS_COMPLETED 136
#define IDS_DEVICE_MODEL_MOTOROLA_DROIDX2 137
#define IDS_NULLSOFT_WIFI_DEVICE_PLUGIN 65534
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 139
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

View File

@ -0,0 +1,39 @@
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#include "../../../Winamp/buildType.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,56,0,0
PRODUCTVERSION WINAMP_PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "Winamp SA"
VALUE "FileDescription", "Winamp Portable Device Plug-in"
VALUE "FileVersion", "1,56,0,0"
VALUE "InternalName", "Nullsoft Wi-Fi Device"
VALUE "LegalCopyright", "Copyright <20> 2010-2023 Winamp SA"
VALUE "LegalTrademarks", "Nullsoft and Winamp are trademarks of Winamp SA"
VALUE "OriginalFilename", "pmp_wifi.dll"
VALUE "ProductName", "Winamp"
VALUE "ProductVersion", STR_WINAMP_PRODUCTVER
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END