#include "api.h"
#include "iPodInfo.h"
#include "resource.h"
#include "../../General/gen_ml/ml.h"
#include "../../Library/ml_pmp/pmp.h"

#include "../xml/obj_xml.h"
#include "../plist/loader.h"

#include <api/service/waservicefactory.h>

#include <stdio.h>
#include <windows.h>
#include <strsafe.h>

extern PMPDevicePlugin plugin;

static const ArtworkFormat ipod_color_artwork_info[] =
{
	{THUMB_COVER_SMALL,        56,  56, 1017, RGB_565, 4, 4},
	{THUMB_COVER_LARGE,       140, 140, 1016, RGB_565, 4, 4},
	{THUMB_PHOTO_TV_SCREEN,   720, 480, 1019, RGB_565, 4, 4},
	{THUMB_PHOTO_LARGE,       130,  88, 1015, RGB_565, 4, 4},
	{THUMB_PHOTO_FULL_SCREEN, 220, 176, 1013, RGB_565, 4, 4},
	{THUMB_PHOTO_SMALL,        42,  30, 1009, RGB_565, 4, 4},
	{THUMB_INVALID,            -1,  -1,   -1, RGB_565, 4, 4}
};

static const ArtworkFormat ipod_nano_artwork_info[] =
{
	{THUMB_COVER_SMALL,        42,  42, 1031, RGB_565, 4, 4},
	{THUMB_COVER_LARGE,       100, 100, 1027, RGB_565, 4, 4},
	{THUMB_PHOTO_LARGE,        42,  37, 1032, RGB_565, 4, 4},
	{THUMB_PHOTO_FULL_SCREEN, 176, 132, 1023, RGB_565, 4, 4},
	{THUMB_INVALID,            -1,  -1,   -1, RGB_565, 4, 4}
};

static const ArtworkFormat ipod_video_artwork_info[] =
{
	{THUMB_COVER_SMALL,       100, 100, 1028, RGB_565, 4, 4},
	{THUMB_COVER_LARGE,       200, 200, 1029, RGB_565, 4, 4},
	{THUMB_PHOTO_TV_SCREEN,   720, 480, 1019, RGB_565, 4, 4},
	{THUMB_PHOTO_LARGE,       130,  88, 1015, RGB_565, 4, 4},
	{THUMB_PHOTO_FULL_SCREEN, 320, 240, 1024, RGB_565, 4, 4},
	{THUMB_PHOTO_SMALL,        50,  41, 1036, RGB_565, 4, 4},
	{THUMB_INVALID,            -1,  -1,   -1, RGB_565, 4, 4}
};

static const ArtworkFormat ipod_7g_artwork_info[] =
{
	{THUMB_COVER_SMALL,        55,  55, 1061, RGB_565, 4, 4},
	{THUMB_COVER_MEDIUM1,     128, 128, 1055, RGB_565, 4, 4},
	{THUMB_COVER_LARGE,       320, 320, 1060, RGB_565, 4, 4},
	{THUMB_INVALID,            -1,  -1,   -1, RGB_565, 4, 4}
};

static const ArtworkFormat ipod_touch_artwork_info[] =
{
	{THUMB_COVER_SMALL,        55,  55, 3006, RGB_555, 16, 4096},
	{THUMB_COVER_MEDIUM1,      64,  64, 3003, RGB_555_REC, 16, 4096},
	{THUMB_COVER_MEDIUM2,      88,  88, 3007, RGB_555, 16, 4096},
	{THUMB_COVER_MEDIUM3,     128, 128, 3002, RGB_555_REC, 16, 4096},
	{THUMB_COVER_MEDIUM4,     256, 256, 3001, RGB_555_REC, 16, 4096},
	{THUMB_COVER_LARGE,       320, 320, 3005, RGB_555, 16, 4096},
	{THUMB_INVALID,            -1,  -1,   -1, RGB_555, 4, 4}
};

/*
static const ArtworkFormat ipod_mobile_1_artwork_info[] = {
	{THUMB_COVER_SMALL,        50,  50, 2002},
	{THUMB_COVER_LARGE,       150, 150, 2003},
	{THUMB_INVALID,            -1,  -1,   -1}
};
*/

//maps model to artwork format
static const ArtworkFormat *ipod_artwork_info_table[] =
{
	NULL,                      // invalid
	ipod_color_artwork_info,   // color
	NULL,                      // regular
	NULL,                      // mini
	NULL,                      // shuffle
	ipod_video_artwork_info,   // video
	ipod_nano_artwork_info,    // nano
	ipod_7g_artwork_info,      // classic
	ipod_7g_artwork_info,      // fat nano
	ipod_touch_artwork_info,   // touch
};


// this list compiled from http://www.thismuchiknow.co.uk/?page_id=27 and is kept in the same order as that table for easy updating
// when new ipods come out, let's keep this up to date.
// at the moment this is just used as a mapping from part number to model, for album art
static const iPodModelInfo ipod_info_table[] =
{
	//1st gen ipods
	{L"8513",   IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //mac
	{L"8541",   IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //mac
	{L"8697",   IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //pc
	{L"8709",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //mac

	//2nd gen ipods
	{L"8737",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //mac
	{L"8740",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //pc
	{L"8738",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //mac
	{L"8741",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //pc

	//3rd gen ipods
	{L"8976",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"8946",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"8948",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9244",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9245",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9460",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	//1st gen mini
	{L"9160",   IPOD_MODEL_MINI,    IPOD_COLOR_SILVER, IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9436",   IPOD_MODEL_MINI,    IPOD_COLOR_BLUE,   IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9435",   IPOD_MODEL_MINI,    IPOD_COLOR_PINK,   IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9434",   IPOD_MODEL_MINI,    IPOD_COLOR_GREEN,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9437",   IPOD_MODEL_MINI,    IPOD_COLOR_GOLD,   IDB_CLASSIC_16, IDB_CLASSIC_160},

	//4th gen ipods
	{L"9282",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9268",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"E435",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //HP branded
	{L"E436",  IPOD_MODEL_REGULAR, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //HP	branded
	{L"9787",  IPOD_MODEL_REGULAR, IPOD_COLOR_U2,     IDB_CLASSIC_16, IDB_CLASSIC_160},

	//4th gen ipod photos
	{L"9585",  IPOD_MODEL_COLOR,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9586",  IPOD_MODEL_COLOR,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	//shuffles
	{L"A133", IPOD_MODEL_SHUFFLE, IPOD_COLOR_WHITE,  IDB_SHUFFLE1G_16, IDB_SHUFFLE1G_160},
	{L"9724", IPOD_MODEL_SHUFFLE, IPOD_COLOR_WHITE,  IDB_SHUFFLE1G_16, IDB_SHUFFLE1G_160},
	{L"9725",   IPOD_MODEL_SHUFFLE, IPOD_COLOR_WHITE,  IDB_SHUFFLE1G_16, IDB_SHUFFLE1G_160},

	// more ipod photos
	{L"9829",  IPOD_MODEL_COLOR,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9830",  IPOD_MODEL_COLOR,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	// ipod mini 2nd gen
	{L"9959",   IPOD_MODEL_MINI,    IPOD_COLOR_SILVER, IDB_CLASSIC_16, IDB_CLASSIC_160}, // pepsi giveaway ipod
	{L"9800",   IPOD_MODEL_MINI,    IPOD_COLOR_SILVER, IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9802",   IPOD_MODEL_MINI,    IPOD_COLOR_BLUE,   IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9804",   IPOD_MODEL_MINI,    IPOD_COLOR_PINK,   IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9806",   IPOD_MODEL_MINI,    IPOD_COLOR_GREEN,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9801",   IPOD_MODEL_MINI,    IPOD_COLOR_SILVER, IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9803",   IPOD_MODEL_MINI,    IPOD_COLOR_BLUE,   IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9805",   IPOD_MODEL_MINI,    IPOD_COLOR_PINK,   IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"9807",   IPOD_MODEL_MINI,    IPOD_COLOR_GREEN,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	//HP colour ipods
	{L"S492",  IPOD_MODEL_COLOR,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"S493",  IPOD_MODEL_COLOR,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	//HP ipod mini 2nd gen
	{L"W753",   IPOD_MODEL_MINI,    IPOD_COLOR_SILVER, IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"X762",   IPOD_MODEL_MINI,    IPOD_COLOR_SILVER, IDB_CLASSIC_16, IDB_CLASSIC_160},

	//more 4th gen ipod photos
	{L"A079",  IPOD_MODEL_COLOR,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A127",  IPOD_MODEL_COLOR,   IPOD_COLOR_U2,     IDB_CLASSIC_16, IDB_CLASSIC_160},

	//HP ipod shuffles
	{L"X765", IPOD_MODEL_SHUFFLE, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"X766",   IPOD_MODEL_SHUFFLE, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	/*
	//harry potter ipod 4G, don't know serial number. but that's ok because it was only on sale for a month, so fuck it.
	{L"????",  IPOD_MODEL_COLOR,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	*/

	//ipod nano 1st gen
	{L"A004",   IPOD_MODEL_NANO,    IPOD_COLOR_WHITE,  IDB_NANO1G_16, IDB_NANO1G_160},
	{L"A099",   IPOD_MODEL_NANO,    IPOD_COLOR_BLACK,  IDB_NANO1G_16, IDB_NANO1G_160},
	{L"A005",   IPOD_MODEL_NANO,    IPOD_COLOR_WHITE,  IDB_NANO1G_16, IDB_NANO1G_160},
	{L"A107",   IPOD_MODEL_NANO,    IPOD_COLOR_BLACK,  IDB_NANO1G_16, IDB_NANO1G_160},

	//ipod video
	{L"A002",  IPOD_MODEL_VIDEO,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A146",  IPOD_MODEL_VIDEO,   IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A003",  IPOD_MODEL_VIDEO,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A147",  IPOD_MODEL_VIDEO,   IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A253",  IPOD_MODEL_VIDEO,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160}, //harry potter ipod 5G

	//1gig nano
	{L"A350",   IPOD_MODEL_NANO,    IPOD_COLOR_WHITE,  IDB_NANO1G_16, IDB_NANO1G_160},
	{L"A352",   IPOD_MODEL_NANO,    IPOD_COLOR_BLACK,  IDB_NANO1G_16, IDB_NANO1G_160},

	// U2 ipod video
	{L"A452",  IPOD_MODEL_VIDEO,   IPOD_COLOR_U2,     IDB_CLASSIC_16, IDB_CLASSIC_160},

	//2nd gen nano
	{L"A477",   IPOD_MODEL_NANO,    IPOD_COLOR_SILVER, IDB_NANO2G_16, IDB_NANO2G_160},
	{L"A426",   IPOD_MODEL_NANO,    IPOD_COLOR_SILVER, IDB_NANO2G_16, IDB_NANO2G_160},
	{L"A428",   IPOD_MODEL_NANO,    IPOD_COLOR_BLUE,   IDB_NANO2G_16, IDB_NANO2G_160},
	{L"A487",   IPOD_MODEL_NANO,    IPOD_COLOR_GREEN,  IDB_NANO2G_16, IDB_NANO2G_160},
	{L"A489",   IPOD_MODEL_NANO,    IPOD_COLOR_PINK,   IDB_NANO2G_16, IDB_NANO2G_160},
	{L"A497",   IPOD_MODEL_NANO,    IPOD_COLOR_BLACK,  IDB_NANO2G_16, IDB_NANO2G_160},

	// ipod video 6th gen
	{L"A444",  IPOD_MODEL_VIDEO,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A446",  IPOD_MODEL_VIDEO,   IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A448",  IPOD_MODEL_VIDEO,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A450",  IPOD_MODEL_VIDEO,   IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	//2nd gen shuffle
	{L"A564",   IPOD_MODEL_SHUFFLE, IPOD_COLOR_SILVER, IDB_SHUFFLE2G_16, IDB_SHUFFLE2G_160},

	// ipod video u2 6th gen
	{L"A664",  IPOD_MODEL_VIDEO,   IPOD_COLOR_U2,     IDB_CLASSIC_16, IDB_CLASSIC_160},

	//product red ipod nano
	{L"A725",   IPOD_MODEL_NANO,    IPOD_COLOR_RED,    IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A899",   IPOD_MODEL_NANO,    IPOD_COLOR_RED,    IDB_CLASSIC_16, IDB_CLASSIC_160},

	// coloured versions of ipod shuffle 2nd gen
	{L"A947",   IPOD_MODEL_SHUFFLE, IPOD_COLOR_PINK,   IDB_SHUFFLE2G_16, IDB_SHUFFLE2G_160},
	{L"A949",   IPOD_MODEL_SHUFFLE, IPOD_COLOR_BLUE,   IDB_SHUFFLE2G_16, IDB_SHUFFLE2G_160},
	{L"A951",   IPOD_MODEL_SHUFFLE, IPOD_COLOR_GREEN,  IDB_SHUFFLE2G_16, IDB_SHUFFLE2G_160},
	{L"A953",   IPOD_MODEL_SHUFFLE, IPOD_COLOR_ORANGE, IDB_SHUFFLE2G_16, IDB_SHUFFLE2G_160},

	// fat nanos
	{L"A978",   IPOD_MODEL_FATNANO, IPOD_COLOR_SILVER, IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A980",   IPOD_MODEL_FATNANO, IPOD_COLOR_SILVER, IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"B249",   IPOD_MODEL_FATNANO, IPOD_COLOR_BLUE,   IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"B253",   IPOD_MODEL_FATNANO, IPOD_COLOR_GREEN,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"B261",   IPOD_MODEL_FATNANO, IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"B257",   IPOD_MODEL_FATNANO, IPOD_COLOR_RED,    IDB_CLASSIC_16, IDB_CLASSIC_160},

	// ipod classic
	{L"B147",  IPOD_MODEL_CLASSIC, IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"B029",  IPOD_MODEL_CLASSIC, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"B150", IPOD_MODEL_CLASSIC, IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"B145", IPOD_MODEL_CLASSIC, IPOD_COLOR_WHITE,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	// ipod touch
	{L"A623",   IPOD_MODEL_TOUCH,   IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},
	{L"A627",  IPOD_MODEL_TOUCH,   IPOD_COLOR_BLACK,  IDB_CLASSIC_16, IDB_CLASSIC_160},

	//insert info about new models here (be sure to take first char off the product code)...
};

static const iPodModelInfo 
shuffle1g_info = {L"XXXX", IPOD_MODEL_SHUFFLE, IPOD_COLOR_PINK,   IDB_SHUFFLE1G_16, IDB_SHUFFLE1G_160},
shuffle2g_info = {L"XXXX", IPOD_MODEL_SHUFFLE, IPOD_COLOR_PINK,   IDB_SHUFFLE2G_16, IDB_SHUFFLE2G_160},
shuffle3g_info = {L"XXXX", IPOD_MODEL_SHUFFLE, IPOD_COLOR_SILVER, IDB_SHUFFLE3G_16, IDB_SHUFFLE3G_160},
shuffle4g_info = {L"XXXX", IPOD_MODEL_SHUFFLE, IPOD_COLOR_SILVER, IDB_SHUFFLE4G_16, IDB_SHUFFLE4G_160},
classic_info   = {L"XXXX", IPOD_MODEL_CLASSIC, IPOD_COLOR_WHITE,  IDB_CLASSIC_16,   IDB_CLASSIC_160},
video_info     = {L"XXXX", IPOD_MODEL_VIDEO,   IPOD_COLOR_WHITE,  IDB_CLASSIC_16,   IDB_CLASSIC_160},
nano1g_info    = {L"XXXX", IPOD_MODEL_NANO,    IPOD_COLOR_WHITE,  IDB_NANO1G_16,    IDB_NANO1G_160},
nano2g_info    = {L"XXXX", IPOD_MODEL_NANO,    IPOD_COLOR_WHITE,  IDB_NANO2G_16,    IDB_NANO2G_160},
nano3g_info    = {L"XXXX", IPOD_MODEL_NANO,    IPOD_COLOR_WHITE,  IDB_NANO3G_16,    IDB_NANO3G_160},
nano4g_info    = {L"XXXX", IPOD_MODEL_NANO,    IPOD_COLOR_WHITE,  IDB_NANO4G_16,    IDB_NANO4G_160};

static INT_PTR CALLBACK selectipodtype_dlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_INITDIALOG:
	{
		BringWindowToTop(hwndDlg);
		wchar_t * sysinfo = (wchar_t*)lParam;
		SetWindowLongPtr(hwndDlg,GWLP_USERDATA,lParam);
		wchar_t path[] = {sysinfo[0],L":\\"};
		wchar_t name[32] = {0};
		GetVolumeInformation(path,name,32,NULL,NULL,NULL,NULL,0);
		wchar_t buf[100] = {0};
		wchar_t s[32] = {0};
		GetDlgItemText(hwndDlg,IDC_IPODINFO,s,32);
		StringCchPrintf(buf,100,L"%s (%s) %s",path,name,s);
		SetDlgItemText(hwndDlg,IDC_IPODINFO,buf);
	}
	break;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDC_RADIO1:
		case IDC_RADIO2:
		case IDC_RADIO3:
		case IDC_RADIO4:
		case IDC_RADIO5:
		case IDC_RADIO6:
		case IDC_RADIO7:
		case IDC_RADIO8:
			EnableWindow(GetDlgItem(hwndDlg,IDOK),TRUE);
			break;
		case IDCANCEL:
			EndDialog(hwndDlg,1);
			break;
		case IDOK:
		{
			char *m;
			if (IsDlgButtonChecked(hwndDlg,IDC_RADIO1)) m = "A133"; //shuffle
			else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO2)) m = "9586"; //photo
			else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO3)) m = "A002"; //video
			else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO4)) m = "A005"; //nano
			else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO6)) m = "A623"; //touch
			else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO7)) m = "B145"; //classic
			else if (IsDlgButtonChecked(hwndDlg,IDC_RADIO8)) m = "B257"; //fatnano
			else m = "8976"; //other
			wchar_t * sysinfo = (wchar_t*)GetWindowLongPtr(hwndDlg,GWLP_USERDATA);
			FILE *f = _wfopen(sysinfo,L"a+b");
			if (f)
			{
				fprintf(f,"ModelNumStr: M%s\n",m);
				fclose(f);
			}
		}
		EndDialog(hwndDlg,0);
		break;
		}
		break;
	}
	return 0;
}

/* This table was extracted from ipod-model-table from podsleuth svn trunk
 * on 2008-06-14 (which seems to match podsleuth 0.6.2)
*/
static const iPodSerialToModel serial_to_model_mapping[] =
{
	{ L"LG6", L"8541" },
	{ L"NAM", L"8541" },
	{ L"MJ2", L"8541" },
	{ L"ML1", L"8709" },
	{ L"MME", L"8709" },
	{ L"MMB", L"8737" },
	{ L"MMC", L"8738" },
	{ L"NGE", L"8740" },
	{ L"NGH", L"8740" },
	{ L"MMF", L"8741" },
	{ L"NLW", L"8946" },
	{ L"NRH", L"8976" },
	{ L"QQF", L"9460" },
	{ L"PQ5", L"9244" },
	{ L"PNT", L"9244" },
	{ L"NLY", L"8948" },
	{ L"NM7", L"8948" },
	{ L"PNU", L"9245" },
	{ L"PS9", L"9282" },
	{ L"Q8U", L"9282" },
	{ L"V9V", L"9787" },
	{ L"S2X", L"9787" },
	{ L"PQ7", L"9268" },
	{ L"TDU", L"A079" },
	{ L"TDS", L"A079" },
	{ L"TM2", L"A127" },
	{ L"SAZ", L"9830" },
	{ L"SB1", L"9830" },
	{ L"SAY", L"9829" },
	{ L"R5Q", L"9585" },
	{ L"R5R", L"9586" },
	{ L"R5T", L"9586" },
	{ L"PFW", L"9160" },
	{ L"PRC", L"9160" },
	{ L"QKL", L"9436" },
	{ L"QKQ", L"9436" },
	{ L"QKK", L"9435" },
	{ L"QKP", L"9435" },
	{ L"QKJ", L"9434" },
	{ L"QKN", L"9434" },
	{ L"QKM", L"9437" },
	{ L"QKR", L"9437" },
	{ L"S41", L"9800" },
	{ L"S4C", L"9800" },
	{ L"S43", L"9802" },
	{ L"S45", L"9804" },
	{ L"S47", L"9806" },
	{ L"S4J", L"9806" },
	{ L"S42", L"9801" },
	{ L"S44", L"9803" },
	{ L"S48", L"9807" },
	{ L"RS9", L"9724" },
	{ L"QGV", L"9724" },
	{ L"TSX", L"9724" },
	{ L"PFV", L"9724" },
	{ L"R80", L"9724" },
	{ L"RSA", L"9725" },
	{ L"TSY", L"9725" },
	{ L"C60", L"9725" },
	{ L"VTE", L"A546" },
	{ L"VTF", L"A546" },
	{ L"XQ5", L"A947" },
	{ L"XQS", L"A947" },
	{ L"XQV", L"A949" },
	{ L"XQX", L"A949" },
	{ L"YX7", L"A949" },
	{ L"XQY", L"A951" },
	{ L"YX8", L"A951" },
	{ L"XR1", L"A953" },
	{ L"YXA", L"B233" },
	{ L"YX6", L"B225" },
	{ L"YX7", L"B228" },
	{ L"YX9", L"B225" },
	{ L"UNA", L"A350" },
	{ L"UNB", L"A350" },
	{ L"UPR", L"A352" },
	{ L"UPS", L"A352" },
	{ L"SZB", L"A004" },
	{ L"SZV", L"A004" },
	{ L"SZW", L"A004" },
	{ L"SZC", L"A005" },
	{ L"SZT", L"A005" },
	{ L"TJT", L"A099" },
	{ L"TJU", L"A099" },
	{ L"TK2", L"A107" },
	{ L"TK3", L"A107" },
	{ L"VQ5", L"A477" },
	{ L"VQ6", L"A477" },
	{ L"V8T", L"A426" },
	{ L"V8U", L"A426" },
	{ L"V8W", L"A428" },
	{ L"V8X", L"A428" },
	{ L"VQH", L"A487" },
	{ L"VQJ", L"A487" },
	{ L"VQK", L"A489" },
	{ L"VKL", L"A489" },
	{ L"WL2", L"A725" },
	{ L"WL3", L"A725" },
	{ L"X9A", L"A726" },
	{ L"X9B", L"A726" },
	{ L"VQT", L"A497" },
	{ L"VQU", L"A497" },
	{ L"Y0P", L"A978" },
	{ L"Y0R", L"A980" },
	{ L"YXR", L"B249" },
	{ L"YXV", L"B257" },
	{ L"YXT", L"B253" },
	{ L"YXX", L"B261" },
	{ L"SZ9", L"A002" },
	{ L"WEC", L"A002" },
	{ L"WED", L"A002" },
	{ L"WEG", L"A002" },
	{ L"WEH", L"A002" },
	{ L"WEL", L"A002" },
	{ L"TXK", L"A146" },
	{ L"TXM", L"A146" },
	{ L"WEE", L"A146" },
	{ L"WEF", L"A146" },
	{ L"WEJ", L"A146" },
	{ L"WEK", L"A146" },
	{ L"SZA", L"A003" },
	{ L"SZU", L"A003" },
	{ L"TXL", L"A147" },
	{ L"TXN", L"A147" },
	{ L"V9K", L"A444" },
	{ L"V9L", L"A444" },
	{ L"WU9", L"A444" },
	{ L"VQM", L"A446" },
	{ L"V9M", L"A446" },
	{ L"V9N", L"A446" },
	{ L"WEE", L"A446" },
	{ L"V9P", L"A448" },
	{ L"V9Q", L"A448" },
	{ L"V9R", L"A450" },
	{ L"V9S", L"A450" },
	{ L"V95", L"A450" },
	{ L"V96", L"A450" },
	{ L"WUC", L"A450" },
	{ L"W9G", L"A664" }, /* 30GB iPod Video U2 5.5g */
	{ L"Y5N", L"B029" }, /* Silver Classic 80GB */
	{ L"YMV", L"B147" }, /* Black Classic 80GB */
	{ L"YMU", L"B145" }, /* Silver Classic 160GB */
	{ L"YMX", L"B150" }, /* Black Classic 160GB */
	{ L"2C5", L"B562" }, /* Silver Classic 120GB */
	{ L"2C7", L"B565" }, /* Black Classic 120GB */
	{ L"9ZS", L"C293" }, /* Silver Classic 160GB (2009) */
	{ L"9ZU", L"C297" }, /* Black Classic 160GB (2009) */

	{ L"37P", L"B663" }, /* 4GB Green Nano 4g */
	{ L"37Q", L"B666" }, /* 4GB Yellow Nano 4g */
	{ L"37H", L"B654" }, /* 4GB Pink Nano 4g */
	{ L"1P1", L"B480" }, /* 4GB Silver Nano 4g */
	{ L"37K", L"B657" }, /* 4GB Purple Nano 4g */
	{ L"37L", L"B660" }, /* 4GB Orange Nano 4g */
	{ L"2ME", L"B598" }, /* 8GB Silver Nano 4g */
	{ L"3QS", L"B732" }, /* 8GB Blue Nano 4g */
	{ L"3QT", L"B735" }, /* 8GB Pink Nano 4g */
	{ L"3QU", L"B739" }, /* 8GB Purple Nano 4g */
	{ L"3QW", L"B742" }, /* 8GB Orange Nano 4g */
	{ L"3QX", L"B745" }, /* 8GB Green Nano 4g */
	{ L"3QY", L"B748" }, /* 8GB Yellow Nano 4g */
	{ L"3R0", L"B754" }, /* 8GB Black Nano 4g */
	{ L"3QZ", L"B751" }, /* 8GB Red Nano 4g */
	{ L"5B7", L"B903" }, /* 16GB Silver Nano 4g */
	{ L"5B8", L"B905" }, /* 16GB Blue Nano 4g */
	{ L"5B9", L"B907" }, /* 16GB Pink Nano 4g */
	{ L"5BA", L"B909" }, /* 16GB Purple Nano 4g */
	{ L"5BB", L"B911" }, /* 16GB Orange Nano 4g */
	{ L"5BC", L"B913" }, /* 16GB Green Nano 4g */
	{ L"5BD", L"B915" }, /* 16GB Yellow Nano 4g */
	{ L"5BE", L"B917" }, /* 16GB Red Nano 4g */
	{ L"5BF", L"B918" }, /* 16GB Black Nano 4g */

	{ L"71V", L"C027" }, /* 8GB Silver Nano 5g */
	{ L"71Y", L"C031" }, /* 8GB Black Nano 5g */
	{ L"721", L"C034" }, /* 8GB Purple Nano 5g */
	{ L"726", L"C037" }, /* 8GB Blue Nano 5g */
	{ L"72A", L"C040" }, /* 8GB Green Nano 5g */
	{ L"72F", L"C046" }, /* 8GB Orange Nano 5g */
	{ L"72L", L"C050" }, /* 8GB Pink Nano 5g */

	{ L"72Q", L"C060" }, /* 16GB Silver Nano 5g */
	{ L"72R", L"C062" }, /* 16GB Black Nano 5g */
	{ L"72S", L"C064" }, /* 16GB Purple Nano 5g */
	{ L"72X", L"C066" }, /* 16GB Blue Nano 5g */
	{ L"734", L"C068" }, /* 16GB Green Nano 5g */
	{ L"738", L"C070" }, /* 16GB Yellow Nano 5g */
	{ L"739", L"C072" }, /* 16GB Orange Nano 5g */
	{ L"73A", L"C074" }, /* 16GB Red Nano 5g */
	{ L"73B", L"C075" }, /* 16GB Pink Nano 5g */

	{ L"4NZ", L"B867" }, /* 4GB Silver Shuffle 4g */
	{ L"891", L"C164" }, /* 4GB Black Shuffle 4g */

	{ L"W4T", L"A627" }, /* 16GB Silver iPod Touch (1st gen) */
	{ L"0JW", L"B376" }, /* 32GB Silver iPod Touch (1st gen) */
	{ L"201", L"B528" }, /* 8GB Silver iPod Touch (2nd gen) */
	{ L"203", L"B531" }, /* 16GB Silver iPod Touch (2nd gen) */
	{ L"75J", L"C086" }, /* 8GB Silver iPod Touch (3rd gen) */
	{ L"6K2", L"C008" }, /* 32GB Silver iPod Touch (3rd gen) */
	{ L"6K4", L"C011" }, /* 64GB Silver iPod Touch (3rd gen) */

	{ L"VR0", L"A501" }, /* 4GB Silver iPhone 1st gen */
	{ L"WH8", L"A712" }, /* 8GB Silver iPhone */
	{ L"0KH", L"B384" }, /* 16GB Silver iPhone */
	{ L"Y7H", L"B046" }, /* 8GB Black iPhone 3G */
	{ L"Y7K", L"B496" }, /* 16GB Black iPhone 3G */
	{ L"3NP", L"C131" }, /* 16GB Black iPhone 3GS */
	{ L"3NR", L"C133" }  /* 32GB Black iPhone 3GS */
};

static const wchar_t *GetModelStrForFamilyID(unsigned int familyID)
{
	switch (familyID)
	{
	case 4: // iPod 4
		return L"9282";
	case 5: // iPod 4 (photo)
		return L"9830";
	case 6: // iPod 5
		return L"A002";
	case 7: // nano 1
		return L"A004";
	case 9: // nano 2
		return L"A477";
	case 11: // classic
		return L"B147";
	case 12: // fat nano
		return L"A978";
	case 128: // shuffle
		return L"A133";
	case 130: // shuffle 2
		return L"A947";
	default:
		return 0;
	}
}

static const iPodModelInfo *GetiPodInfoForModelStr(const wchar_t *modelstr)
{
	// now locate this ipod in our table
	int l = sizeof(ipod_info_table)/sizeof(ipod_info_table[0]);
	for (int i=0; i<l; i++)
	{
		if (_wcsnicmp(ipod_info_table[i].model_number,modelstr,wcslen(ipod_info_table[i].model_number))==0)
			return &ipod_info_table[i]; // success!
	}
	return 0;
}

static const iPodModelInfo *GetiPodInfoForFamilyID(unsigned int familyID)
{
	switch(familyID)
	{
	case 6:
		return &video_info;
	case 7:
		return &nano1g_info;
	case 9:
		return &nano2g_info;
	case 11:
		return &classic_info;
	case 12:
		return &nano3g_info;
	case 15:
		return &nano4g_info;
	case 128: 
		return &shuffle1g_info;
	case 130: // shuffle 2G
		return &shuffle2g_info;
	case 132: // shuffle 3G
		return &shuffle3g_info;
	case 133: // shuffle 4G
		return &shuffle4g_info;
	}
	return 0;
}

const wchar_t* GetModelStrForSerialNumber(const wchar_t *serialNumber)
{
	// now locate this ipod in our table
	int l = sizeof(serial_to_model_mapping)/sizeof(iPodSerialToModel);

	INT serialNumberLen = lstrlen(serialNumber);

	if (serialNumberLen < 3)
	{
		return NULL;
	}

	const wchar_t *last3OfSerialNumber = &serialNumber[serialNumberLen-3];

	for (int i=0; i<l; i++)
	{
		int compareRet = CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, last3OfSerialNumber, -1, serial_to_model_mapping[i].serial, -1)-2;
		if (compareRet==0)
			return serial_to_model_mapping[i].model_number; // success!
	}
	return 0;
}

extern bool ParseSysInfoXML(wchar_t drive_letter, char * xml, int xmllen);

iPodInfo::iPodInfo(const iPodModelInfo *_model)
{
	family_id = 0;
	color = _model->color;
	model = _model->model;
	model_number = _wcsdup(_model->model_number);
	image16 = _model->image16;
	image160 = _model->image160;
	fwid=0;
	supportedArtworkFormats=0;
	numberOfSupportedFormats=0;
	shadow_db_version=0;
}

iPodInfo::~iPodInfo()
{
	free(fwid);
	free(model_number);
	delete supportedArtworkFormats;
}

void iPodInfo::SetFWID(const uint8_t *new_fwid)
{
	fwid = (uint8_t *)malloc(8);
	memcpy(fwid, new_fwid, 8);
}

iPodInfo *GetiPodInfo(wchar_t drive)
{
	static const iPodModelInfo unknown = {NULL, IPOD_MODEL_INVALID, IPOD_COLOR_WHITE};

	unsigned char fwid[8]={0};
	bool have_fwid=false;
	char xml[65536] = {0};
	if (ParseSysInfoXML(drive, xml, sizeof(xml)/sizeof(char)))
	{
		// go fetch the FamilyID so we can construct a model string
		DWORD bytesRead = strlen(xml);//sizeof(xml)/sizeof(char);

		// use the plist handler here instead of fishing for the familyid string
		// in the xml

		// instantiate the plist loader
		plistLoader it;

		obj_xml *parser=0;
		waServiceFactory *factory = plugin.service->service_getServiceByGuid(obj_xmlGUID);
		if (factory)
		{
			parser = (obj_xml *)factory->getInterface();
		}

		if (parser)
		{
			// load the XML, this creates an iTunes DB in memory, and returns the	root key
			parser->xmlreader_open();
			parser->xmlreader_registerCallback(L"plist\f*", &it);
			parser->xmlreader_feed(xml, bytesRead);
			parser->xmlreader_feed(0, 0);
			parser->xmlreader_unregisterCallback(&it);
			parser->xmlreader_close();
			plistKey *root_key = &it;
			plistData *root_dict = root_key->getData();
			if (root_dict)
			{
				// get Firewire ID
				plistKey *fwidKey = ((plistDict*)root_dict)->getKey(L"FireWireGUID");
				if (fwidKey)
				{
					plistData *fwidData = fwidKey->getData();
					if (fwidData)
					{
						const wchar_t* p = fwidData->getString();
						for (int i=0; i<8 && *p; i++)
						{
							char num[3]={0,0,0};
							num[0] = *(p++);
							num[1] = *(p++);
							fwid[i] = (uint8_t)strtoul(num,NULL,16);
						}
						have_fwid=true;
					}
				}


				// check for the existance of sqlite
				plistKey *sqliteKey = ((plistDict*)root_dict)->getKey(L"SQLiteDB");
				if (sqliteKey)
				{
					plistData *sqliteData = sqliteKey->getData();
					if (sqliteData)
					{
						const wchar_t* sqliteString = sqliteData->getString();
						if (sqliteString)
						{
							int compareRet = CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, sqliteString, -1, L"1", -1)-2;

							// At this point we dont want to support the sqlite family of ipods
							// so, return unknown if sqlite found
							if (compareRet == 0)
							{
								return 0;
							}
						}
					}
				} // end sqlite check

				// check for FamilyID
				plistKey *familyKey = ((plistDict*)root_dict)->getKey(L"FamilyID");
				if (familyKey)
				{
					plistData *familyData = familyKey->getData();
					if (familyData)
					{
						const wchar_t* familyIDString = familyData->getString();
						if (familyIDString)
						{
							const wchar_t *modelStr = NULL;
							unsigned int familyID = _wtoi(familyIDString);
							// first, try to look up the iPod by family ID
							const iPodModelInfo *info = GetiPodInfoForFamilyID(familyID);
							if (!info)
							{
								modelStr = GetModelStrForFamilyID(familyID);

								// if modelString not apparent, as the case is in most
								// 5th gen nanos and classics
								if (!info && !modelStr)
								{
									plistKey *serialNumberKey = ((plistDict*)root_dict)->getKey(L"SerialNumber");
									if (serialNumberKey)
									{
										plistData *serialNumberData = serialNumberKey->getData();
										if (serialNumberData)
										{
											const wchar_t* serialNumberString = serialNumberData->getString();

											if (serialNumberString)
											{
												modelStr = GetModelStrForSerialNumber(serialNumberString);
											}
										}
									}
								}
							}

							if (modelStr || info)
							{
								if (!info)
									info = GetiPodInfoForModelStr(modelStr);

								if (info)
								{
									iPodInfo* retInfo = new iPodInfo(info);

									if (have_fwid)
										retInfo->SetFWID(fwid);
									
									plistKey *shadow_db_key = ((plistDict*)root_dict)->getKey(L"ShadowDB");
									if (shadow_db_key)
									{
										plistData *shadow_db_data = shadow_db_key->getData();
										if (shadow_db_data && shadow_db_data->getType() == PLISTDATA_BOOLEAN)
										{
											plistBoolean *shadow_db_boolean = (plistBoolean *)shadow_db_data;
											if (shadow_db_boolean->getValue())
												retInfo->shadow_db_version = 1;

											plistKey *shadow_db_version_key = ((plistDict*)root_dict)->getKey(L"ShadowDBVersion");
											if (shadow_db_version_key)
											{
												plistData *shadow_db_version_data = shadow_db_version_key->getData();
												if (shadow_db_version_data && shadow_db_version_data->getType() == PLISTDATA_INTEGER)
												{
													plistInteger *shadow_db_version_integer= (plistInteger *)shadow_db_version_data;
													retInfo->shadow_db_version = shadow_db_version_integer->getValue();
												}
											}
										}
									}
									// now try and populate the ArtworkFormats from the plist
									// looks something like this
									/*****************************************************
									<key>AlbumArt</key>
									<array>
										<key>1069</key>
										<dict>
											<key>FormatId</key>
											<integer>1069</integer>
											<key>RenderWidth</key>
											<integer>142</integer>
											<key>RenderHeight</key>
											<integer>142</integer>
											<key>PixelFormat</key>
											<string>4C353635</string>
											<key>Interlaced</key>
											<false/>
											<key>ColorAdjustment</key>
											<integer>0</integer>
											<key>GammaAdjustment</key>
											<real>2.2</real>
											<key>Crop</key>
											<false/>
											<key>AlignRowBytes</key>
											<true/>
											<key>BackColor</key>
											<string>00000000</string>
											<key>AssociatedFormat</key>
											<integer>131072</integer>
											<key>ExcludedFormats</key>
											<integer>-1</integer>
										</dict>
										<key>1055</key>
										<dict>
											<key>FormatId</key>
											<integer>1055</integer>
											<key>RenderWidth</key>
											<integer>128</integer>
											<key>RenderHeight</key>
											<integer>128</integer>
											<key>PixelFormat</key>
											<string>4C353635</string>
											<key>Interlaced</key>
											<false/>
											<key>ColorAdjustment</key>
											<integer>0</integer>
											<key>GammaAdjustment</key>
											<real>2.2</real>
											<key>Crop</key>
											<true/>
											<key>AlignRowBytes</key>
											<true/>
											<key>BackColor</key>
											<string>00000000</string>
											<key>AssociatedFormat</key>
											<integer>0</integer>
										</dict>
									</array>
									*******************************************************************/

									// look for the AlbumArt dict
									plistKey *albumArtKey = ((plistDict*)root_dict)->getKey(L"AlbumArt");

									if (albumArtKey)
									{
										plistArray* albumArtArray = (plistArray *) albumArtKey->getData();

										if (albumArtArray)
										{
											int numFormats = albumArtArray->getNumItems();
											ArtworkFormat* artworkFormats = new ArtworkFormat[numFormats];


											retInfo->supportedArtworkFormats = &artworkFormats[0];
											retInfo->numberOfSupportedFormats = numFormats;

											for (int i=0;i<numFormats;i++)
											{
												// we need to populate this structure
												/**
												static const ArtworkFormat ipod_color_artwork_info[] = {
														{THUMB_COVER_SMALL,        56,  56, 1017, RGB_565, 4, 4},
														{THUMB_COVER_LARGE,       140, 140, 1016, RGB_565, 4, 4},
														{THUMB_PHOTO_TV_SCREEN,   720, 480, 1019, RGB_565, 4, 4},
														{THUMB_PHOTO_LARGE,       130,  88, 1015, RGB_565, 4, 4},
														{THUMB_PHOTO_FULL_SCREEN, 220, 176, 1013, RGB_565, 4, 4},
														{THUMB_PHOTO_SMALL,        42,  30, 1009, RGB_565, 4, 4},
														{THUMB_INVALID,            -1,  -1,   -1, RGB_565, 4, 4}
													};
												*/
												plistDict *albumArtFormatDict = 0;
												plistData *albumArtFormatKey = (plistKey *)albumArtArray->enumItem(i);
												if (albumArtFormatKey->getType() == PLISTDATA_KEY)
												{
													albumArtFormatDict = (plistDict *)((plistKey *)albumArtFormatKey)->getData();
												}
												else
												{ // Nano 4G doesn't store keys in the AlbumArt array
													albumArtFormatDict = (plistDict *)albumArtFormatKey;
												}

												int numKeys = albumArtFormatDict->getNumKeys();

												if (numKeys)
												{
													for (int j=0; j<numKeys; j++)
													{
														plistKey *albumArtFormatItemKey = albumArtFormatDict->enumKey(j);
														const wchar_t* albumArtFormatKeyName = albumArtFormatItemKey->getName();

														// we need all the arwork formats under AlbumArt, just use
														// a thumb type that we know is accepted
														artworkFormats[i].type = THUMB_COVER_SMALL;

														// these are 4, they just are
														artworkFormats[i].row_align = 4;
														artworkFormats[i].image_align = 4;

														// gather the FormatId
														if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, albumArtFormatKeyName, -1, L"FormatId", -1)-2 == 0)
														{
															const wchar_t* albumArtFormatValue = albumArtFormatItemKey->getData()->getString();
															if (albumArtFormatValue != NULL)
															{
																artworkFormats[i].correlation_id = _wtoi(albumArtFormatValue);
															}
														}
														// gather the RenderWidth
														if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, albumArtFormatKeyName, -1, L"RenderWidth", -1)-2 == 0)
														{
															const wchar_t* albumArtFormatValue = albumArtFormatItemKey->getData()->getString();
															if (albumArtFormatValue != NULL)
															{
																artworkFormats[i].width = _wtoi(albumArtFormatValue);
															}
														}
														// gather the RenderHeight
														if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, albumArtFormatKeyName, -1, L"RenderHeight", -1)-2 == 0)
														{
															const wchar_t* albumArtFormatValue = albumArtFormatItemKey->getData()->getString();
															if (albumArtFormatValue != NULL)
															{
																artworkFormats[i].height = _wtoi(albumArtFormatValue);
															}
														}
														// gather the PixelFormat
														if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, albumArtFormatKeyName, -1, L"PixelFormat", -1)-2 == 0)
														{
															const wchar_t* albumArtFormatValue = albumArtFormatItemKey->getData()->getString();
															if (albumArtFormatValue != NULL)
															{
																artworkFormats[i].format = RGB_565;
															}
														}
													}
												}
											}
										}
									}
									retInfo->family_id = familyID;
									return retInfo;
								}
							}

						}
					}
				} // end familyid
			}
		} // end plist parser
	}

	for (int yy=0; yy<2; yy++)
	{
		wchar_t sysinfo[] = {drive,L":\\iPod_Control\\Device\\SysInfo"};

		FILE *f = _wfopen(sysinfo,L"rt");
		if (f)
		{
			wchar_t *modelnr=NULL;
			wchar_t buf[1024] = {0};
			while (fgetws(buf,1024,f))
			{
				int len = wcslen(buf);
				//snip off trailing newline
				if (len>0 && buf[len-1]==10)
				{
					buf[len-1]=0; len--;
				}
				wchar_t *colon = wcschr(buf,L':');
				if (colon)
				{
					*colon=0;
					if (!wcscmp(L"ModelNumStr",buf))  // found ModelNumStr line..
					{
						modelnr = colon+1;
						while (modelnr && *modelnr == L' ') modelnr++;
						if (!(*modelnr >= L'0' && *modelnr <= L'9')) modelnr++;
						break; // modelnr found, so we're done
					}
				}
			}

			fclose(f);

			if (modelnr && *modelnr)
			{
				const iPodModelInfo *info = GetiPodInfoForModelStr(modelnr);
				if (info)
				{
					iPodInfo* retInfo = new iPodInfo(info);
					if (have_fwid)
						retInfo->SetFWID(fwid);

					return retInfo;
				}
			}
		}
		if (!yy)
		{
			int d = WASABI_API_DIALOGBOXPARAM(IDD_SELECTIPODTYPE,plugin.hwndWinampParent,selectipodtype_dlgproc,(LPARAM)sysinfo);
			if (d) return NULL;
		}
	}
	return new iPodInfo(&unknown);
}

const ArtworkFormat* GetArtworkFormats(const iPodInfo* info)
{
	if (!info) return NULL;
	return ipod_artwork_info_table[info->model];
}