#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 #include #include #include 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; icolor; 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 = ⁢ 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 /***************************************************** AlbumArt 1069 FormatId 1069 RenderWidth 142 RenderHeight 142 PixelFormat 4C353635 Interlaced ColorAdjustment 0 GammaAdjustment 2.2 Crop AlignRowBytes BackColor 00000000 AssociatedFormat 131072 ExcludedFormats -1 1055 FormatId 1055 RenderWidth 128 RenderHeight 128 PixelFormat 4C353635 Interlaced ColorAdjustment 0 GammaAdjustment 2.2 Crop AlignRowBytes BackColor 00000000 AssociatedFormat 0 *******************************************************************/ // 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;ienumItem(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; jenumKey(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]; }