From f4509da9a96cfe8d90abba6f76e3e3e710f1452e Mon Sep 17 00:00:00 2001 From: "Paul N. Richter" Date: Thu, 14 Apr 2016 14:05:47 +0900 Subject: [PATCH] Separated imobile test stuff to imobtest Sorting output Filtering before sorting output --- CMakeLists.txt | 12 ++- imobtest.c | 277 +++++++++++++++++++++++++++++++++++++++++++++++++ lsipod.c | 220 ++++++++++++++++++++++++--------------- lsipod.h | 6 ++ 4 files changed, 428 insertions(+), 87 deletions(-) create mode 100644 imobtest.c diff --git a/CMakeLists.txt b/CMakeLists.txt index b8fd597..1b737f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,18 +3,26 @@ project (lsipod) add_executable(lsipod lsipod.c) set_property(TARGET lsipod APPEND_STRING PROPERTY COMPILE_FLAGS -Wall ) +add_executable(imobtest imobtest.c) +set_property(TARGET imobtest APPEND_STRING PROPERTY COMPILE_FLAGES -Wall ) + find_package(PkgConfig REQUIRED) pkg_search_module(glib-2.0 REQUIRED glib-2.0) pkg_search_module(libgpod-1.0 REQUIRED libgpod-1.0) pkg_search_module(libimobiledevice-1.0 REQUIRED libimobiledevice-1.0) +pkg_search_module(libplist REQUIRED libplist) +find_package(libxml2 REQUIRED) #find_package(glib-2.0 REQUIRED glib-2.0) include_directories(${libgpod-1.0_INCLUDE_DIRS}) include_directories(${libimobiledevice-1.0_INCLUDE_DIRS}) +include_directories(${libplist_INCLUDE_DIRS}) +include_directories(${libxml-2.0_INCLUDE_DIRS}) #set(LIBS ${LIBS} ${glib_LIBRARIES}) -target_link_libraries(lsipod gpod glib-2.0 imobiledevice) +target_link_libraries(lsipod gpod glib-2.0) +target_link_libraries(imobtest gpod glib-2.0 imobiledevice plist xml2) -install(TARGETS lsipod DESTINATION bin) +install(TARGETS lsipod imobtest DESTINATION bin) diff --git a/imobtest.c b/imobtest.c new file mode 100644 index 0000000..1c5f794 --- /dev/null +++ b/imobtest.c @@ -0,0 +1,277 @@ +/** +imobtest.c + +A program to test some of the libimobiledevice APIs. +*/ + +#include +#include +#include +#include + +#include +//#include + +#include +#include +#include +#include + +#include "lsipod.h" + +void test_imobiledevice() ; +void test_springboard(idevice_t device, lockdownd_client_t client) ; +void test_afc(idevice_t device, lockdownd_client_t client) ; + +GError *err ; + +int main(int argc, char *argv[]) { + char *pa ; + + int iarg ; + for(iarg = 1 ; iarg < argc ; iarg++) { + pa = argv[iarg] ; + if('-' == pa[0]) { + switch(pa[1]) { + case 'a': + break ; + case 'd': + break ; + default : + fprintf(stderr, "Unknown option switch:%c\n", pa[1]) ; + } + } + } + + test_imobiledevice() ; + exit(0) ; + + return 0 ; +} + +void notify(const idevice_event_t *ev, void *user_data) { + enum idevice_event_type e = ev->event ; + const char * u = ev->udid ; + + switch(e) { + case IDEVICE_DEVICE_ADD : + printf("Device added\n") ; + break; + case IDEVICE_DEVICE_REMOVE : + printf("Device removed\n") ; + break; + default : + printf("Unknown idevice_event_type\n") ; + } + + printf("Device udid: %s with: %s\n", u, (char *)user_data) ; +} + +void test_imobiledevice() { + char **device_udids ; + int count ; + + char user_data[] = "Some user data" ; + + idevice_event_subscribe(¬ify, (void *)user_data) ; + + idevice_error_t err = idevice_get_device_list(&device_udids, &count) ; + + //printf("Sleeping for 5 seconds...\n") ; + //sleep(5) ; + + if(err == IDEVICE_E_SUCCESS) { + printf("Found %d ilibmobile devices.\n", count) ; + for(int i = 0 ; i < count ; i++) { + uint32_t handle ; + idevice_t device ; + lockdownd_client_t client ; + + idevice_new(&device, device_udids[i]) ; + printf("Just called idevice_new()\n") ; + + idevice_get_handle(device, &handle) ; + printf("Just called idevice_get_handle()\n") ; + + const char *lockdown_label = "foobar" ; + + lockdownd_error_t ld_err = lockdownd_client_new_with_handshake(device, &client, lockdown_label) ; + if(ld_err == LOCKDOWN_E_SUCCESS) { + printf("Successfully created a lockdown client\n") ; + + + char *device_name ; + ld_err = lockdownd_get_device_name(client, &device_name) ; + if(ld_err == LOCKDOWN_E_SUCCESS) { + printf("Device name: %s\n", device_name) ; + free(device_name) ; + } else { + printf("Could not get device name: %d\n", ld_err) ; + } + + + char *service_type ; + ld_err = lockdownd_query_type(client, &service_type) ; + if(ld_err == LOCKDOWN_E_SUCCESS) { + printf("Got service type: %s\n", service_type) ; + //test_springboard(device, client) ; + test_afc(device, client) ; + } else { + printf("Could not query service.\n") ; + } + + lockdownd_client_free(client) ; + printf("Freed the lockdown client\n") ; + + } else { + printf("Could not get a lockdown client\n") ; + } + + //printf("%s with handle %d.\n", device_udids[i], handle) ; + idevice_free(device) ; + printf("Just called idevice_free()\n") ; + + } + } else { + printf("ilibmobiledevice error\n") ; + } + + + idevice_device_list_free(device_udids) ; + idevice_event_unsubscribe() ; +} + + + void test_springboard(idevice_t device, lockdownd_client_t client) { + lockdownd_service_descriptor_t lsd ; + lockdownd_error_t ld_err ; + sbservices_error_t sb_err ; + sbservices_client_t sbclient ; + + //const char *service_id = "com.apple.springboardservices" ; + + ld_err = lockdownd_start_service(client, SBSERVICES_SERVICE_NAME, &lsd) ; + + if(ld_err == LOCKDOWN_E_SUCCESS ){ + printf("Started service: %s\n", SBSERVICES_SERVICE_NAME) ; + + sb_err = sbservices_client_new(device, lsd, &sbclient) ; + //sb_err = sbservices_client_start_service(device, &sbclient, "foobar" ) ; + if(sb_err == SBSERVICES_E_SUCCESS) { + printf("Connected to springboard service.\n") ; + + /* + char *pngdata ; + uint64_t pngsize ; + sb_err = sbservices_get_home_screen_wallpaper_pngdata(sbclient, &pngdata, &pngsize) ; + if(sb_err == SBSERVICES_E_SUCCESS) { + printf("Got wallpaper of size %ld\n", pngsize) ; + } else { + printf("Could not get wallpaper: %d\n", sb_err) ; + } + */ + + + plist_t plist ; + sb_err = sbservices_get_icon_state(sbclient, &plist, NULL) ; + if(sb_err == SBSERVICES_E_SUCCESS) { + printf("Got icon state\n") ; + + + plist_type node_type = plist_get_node_type(plist) ; + printf("Node type: %d\n", node_type) ; + + + if(node_type == PLIST_ARRAY) { + uint32_t array_size = plist_array_get_size(plist) ; + printf("plist is a PLIST_ARRAY of size %d\n", array_size) ; + //plist_t first_elem = plist_array_get_item(plist, 0) ; + /* + char *plist_xml ; + uint32_t xml_len ; + plist_to_xml(plist, &plist_xml, &xml_len) ; + //printf("XML size: %d\n", xml_len) ; + printf("%s\n", plist_xml) ; + free(plist_xml) ; + */ + } + + /* + //char *plist_str ; + //plist_get_string_val(plist, &plist_str) ; + //printf("%s", plist_str) ; + */ + free(plist) ; + } else { + printf("Could not get icon state: %d\n", sb_err) ; + } + + } else { + printf("Could not connect to springboard service.\n") ; + } + sb_err = sbservices_client_free(sbclient) ; + if(sb_err == SBSERVICES_E_SUCCESS) { + printf("Freed sbservices client.\n") ; + } + } else { + printf("Could not start service: %d\n", ld_err) ; + } + + + //sbservices_error_t sb_err = sbservices_client_new(device, ) + } + +void test_afc(idevice_t device, lockdownd_client_t client) { + lockdownd_service_descriptor_t lsd ; + lockdownd_error_t ld_err ; + afc_error_t afc_err ; + afc_client_t afcclient ; + + ld_err = lockdownd_start_service(client, AFC_SERVICE_NAME, &lsd) ; + + if(ld_err == LOCKDOWN_E_SUCCESS ){ + printf("Started service: %s\n", AFC_SERVICE_NAME) ; + + afc_err = afc_client_new(device, lsd, &afcclient) ; + if(afc_err == AFC_E_SUCCESS) { + printf("Connected to afc service.\n") ; + + /* Get device information*/ + char **dev_info ; + afc_err = afc_get_device_info(afcclient, &dev_info) ; + if(afc_err == AFC_E_SUCCESS) { + printf("Got device info.\n") ; + + char **pline = dev_info ; + while(pline && *pline) { + printf("%s\n", *pline) ; + ++pline ; + } + + afc_dictionary_free(dev_info) ; + } else { + printf("Could not get device info.\n") ; + } + + /* Read directory */ + const char root_path[] = "" ; + char **dir_info ; + afc_err = afc_read_directory(afcclient, root_path, &dir_info) ; + if(afc_err == AFC_E_SUCCESS) { + printf("Got directory: %s\n", root_path) ; + afc_dictionary_free(dir_info) ; + } else { + printf("Could not get directory\n") ; + } + + + afc_err = afc_client_free(afcclient) ; + } else { + printf("Could not connect to afc service.\n") ; + } + } else { + printf("Could not start service: %d\n", ld_err) ; + } + +} + diff --git a/lsipod.c b/lsipod.c index bb2c62a..e5efc75 100644 --- a/lsipod.c +++ b/lsipod.c @@ -21,8 +21,6 @@ May be useful for copying from iPod to PC without using iTunes. #include //#include -#include - #include "lsipod.h" struct match_table { @@ -30,42 +28,42 @@ struct match_table { char *title ; char *album ; } ; - + +/* +struct tracklist_and_match { + GList *tracklist ; + struct match_table matches ; +} ; +*/ + void print_track(gpointer track, gpointer user_data) ; void print_db_info(Itdb_iTunesDB *db) ; -void print_mounted_ipods() ; -int get_mounted_ipods(char *mounted_ipods[], size_t arr_size) ; -void list_ipod_contents(const char *mnt_point, const struct match_table *matches) ; +//void print_mounted_ipods() ; +int get_mounted_ipods(char mounted_ipods[][32], size_t arr_size) ; +void list_ipod_contents(const char *mnt_point, struct match_table *matches) ; int is_rchr(const char *str, char c) ; -void test_imobiledevice() ; +gint comp_tracks(gconstpointer a, gconstpointer b) ; +void add_filtered_track(gpointer data, gpointer user_data) ; +GList *filter_tracks(GList *tracks, struct match_table *matches); GError *err ; - - int main(int argc, char *argv[]) { - /* - if(argc > 2) { - - - } - */ - char *pa ; - - test_imobiledevice() ; - exit(0) ; - //struct match_table matches ; + - struct match_table matches = + struct match_table matches = { NULL, NULL, NULL } ; + //uint matches = 0 ; + + const char *selected_mount = NULL ; int iarg ; for(iarg = 1 ; iarg < argc ; iarg++) { @@ -73,20 +71,26 @@ int main(int argc, char *argv[]) { if('-' == pa[0]) { switch(pa[1]) { case 'a': + //matches |= MATCH_ARTIST ; matches.artist = argv[++iarg] ; printf("Option: match artist: %s\n", argv[iarg]) ; break ; case 'd': + //matches |= MATCH_ALBUM ; matches.album = argv[++iarg] ; printf("Option: match album: %s\n", argv[iarg]) ; break ; case 't': + //matches |= MATCH_TITLE ; matches.title = argv[++iarg] ; printf("Option: match title: %s\n", argv[iarg]) ; break ; case 'v' : printf("lsipod Version %d.%d\n", lsipod_VERSION_MAJOR, lsipod_VERSION_MINOR) ; break ; + case 'm': + selected_mount = argv[++iarg] ; + break ; default : fprintf(stderr, "Unknown option switch:%c\n", pa[1]) ; } @@ -98,7 +102,7 @@ int main(int argc, char *argv[]) { //exit(0) ; - char *mounts[MAX_NUM_MOUNTED_IPODS] ; + char mounts[MAX_NUM_MOUNTED_IPODS][32] ; int num_ipods ; int i = 0; @@ -107,6 +111,15 @@ int main(int argc, char *argv[]) { num_ipods = get_mounted_ipods(mounts, sizeof(mounts) / sizeof(*mounts)) ; + if(selected_mount) { + for(i = 0 ; i < num_ipods ; i++) { + if(!strcmp(mounts[i], selected_mount)) { + num_ipods = 1 ; + break ; + } + } + } + switch(num_ipods) { case 0 : printf("No mounted ipods found.\n") ; @@ -116,8 +129,9 @@ int main(int argc, char *argv[]) { list_ipod_contents(mounts[i], &matches) ; break ; default : + printf("We found %d mounts.\n", num_ipods) ; for(i = 0 ; i < num_ipods ; i++) { - printf("Found a mounted ipod at: %s.\n", mounts[i]) ; + printf("Found a mounted ipod at: %s\n", mounts[i]) ; } printf("Please specify which one you want to list.\n") ; } @@ -135,7 +149,16 @@ int main(int argc, char *argv[]) { return 0 ; } -void list_ipod_contents(const char *mnt_point, const struct match_table *matches) { + +gint comp_tracks(gconstpointer a, gconstpointer b) { + Itdb_Track *track_a = (Itdb_Track *)a ; + Itdb_Track *track_b = (Itdb_Track *)b ; + + return g_strcmp0(track_a->album, track_b->album) ; + //return track_a->time_added - track_b->time_added ; +} + +void list_ipod_contents(const char *mnt_point, struct match_table *matches) { //test() ; Itdb_iTunesDB *db = itdb_parse(mnt_point , &err) ; @@ -152,14 +175,78 @@ void list_ipod_contents(const char *mnt_point, const struct match_table *matches (matches->title == NULL) && (matches->album == NULL)) { matches = NULL ; + printf("No filters.\n") ; } - g_list_foreach(db->tracks, print_track, (gpointer)matches) ; + printf("iPod contains %d tracks.\n", g_list_length(db->tracks)) ; + //return ; + + + //printf("iPod contains %d tracks.\n", g_list_length(sorted)) ; + + // g_list_foreach(db->tracks, print_track, (gpointer)matches) ; + //g_list_foreach(sorted, print_track, (gpointer)&matches) ; + + GList *filtered_tracks = filter_tracks(db->tracks, matches) ; + GList *sorted_tracks = g_list_sort(filtered_tracks, comp_tracks) ; + + g_list_foreach(sorted_tracks, print_track, NULL) ; + + + g_list_free(sorted_tracks) ; + // g_list_free(filtered_tracks) ; itdb_free(db) ; } +/* filter first, sort later */ +GList *filter_tracks(GList *tracks, struct match_table *matches) { + if (!matches) { return tracks ; } + //GList *filtered_tracks = NULL ; + + /* hack together an array containing the two values we need to pass + to g_list_foreach(). The sorted list will successively built on to list_and_filter[0] + */ + void *list_and_filter[] = { + NULL, + //(void *)filtered_tracks, + (void *)matches, + } ; + + g_list_foreach(tracks, add_filtered_track, list_and_filter) ; + + printf("Filtered list is now length %d\n", g_list_length(list_and_filter[0])) ; + return list_and_filter[0] ; +} + +void add_filtered_track(gpointer data, gpointer user_data) { + Itdb_Track *track = (Itdb_Track *)data ; + + /* crack open the filtered tracks adn matches*/ + void **list_and_filter = (void **)user_data ; + + GList *filtered_tracks = (GList *)list_and_filter[0] ; + struct match_table *matches = (struct match_table *)list_and_filter[1] ; + + if(track_passes_filter(track, matches)) { + list_and_filter[0] = g_list_prepend(filtered_tracks, track) ; + //printf("Passing track through filter:%s: %s\n", track->artist, track->title) ; + //printf("Selection list length: %d\n", g_list_length(list_and_filter[0])) ; + } +} + +gboolean track_passes_filter(Itdb_Track *track, struct match_table *matches) { + if(!matches) { return TRUE ; } + + return ( + (track->artist && matches->artist && g_strrstr(track->artist, matches->artist)) || + (track->title && matches->title && g_strrstr(track->title, matches->title)) || + (track->album && matches->album && g_strrstr(track->album, matches->album)) + ) ; +} + +/* void print_mounted_ipods() { // struct mntent m ; #ifdef __linux @@ -183,18 +270,20 @@ void print_mounted_ipods() { } #endif } +*/ -int get_mounted_ipods(char *mounted_ipods[], size_t arr_size) { +int get_mounted_ipods(char mounted_ipods[][32], size_t arr_size) { int num_ipod_mounts = 0 ; Itdb_iTunesDB *db ; char *mnt_dir ; - + #ifdef __linux const struct mntent *pm ; FILE *mtab = setmntent("/etc/mtab", "r") ; while((pm = getmntent(mtab))) { mnt_dir = pm->mnt_dir ; + //mnt_dir = pm->mnt_fsname ; #else struct statfs *pm ; int num_mounts, i ; @@ -205,12 +294,17 @@ int get_mounted_ipods(char *mounted_ipods[], size_t arr_size) { mnt_dir = pm[i].f_mntonname ; #endif err = NULL ; - db = itdb_parse(mnt_dir, &err) ; - if (db) { + //printf("get_mounted_ipods() : %s\n", mnt_dir) ; + + + if ((db = itdb_parse(mnt_dir, &err))) { if(num_ipod_mounts < arr_size) { - *mounted_ipods++ = mnt_dir ; + printf("get_mounted_ipods() : %s\n", mnt_dir) ; + strncpy(*mounted_ipods, mnt_dir, sizeof(mounted_ipods[0])) ; + //*mounted_ipods = mnt_dir ; num_ipod_mounts++ ; + mounted_ipods++ ; } itdb_free(db) ; } @@ -243,12 +337,23 @@ void print_track(gpointer data, gpointer user_data) { struct match_table *matches = (struct match_table *)user_data ; // gchar *artist = track->artist ; + //uint matches = (int)(*user_data) ; + if((!matches) || (track->artist && matches->artist && g_strrstr(track->artist, matches->artist)) || (track->title && matches->title && g_strrstr(track->title, matches->title)) || (track->album && matches->album && g_strrstr(track->album, matches->album)) ) { + + /* + if((matches == 0) || + (track->artist && (matches & MATCH_ARTIST) && g_strrstr(track->artist, matches->artist)) || + (track->title && (matches & MATCH_TITLE) && g_strrstr(track->title, matches->title)) || + (track->album && (matches & MATCH_ALBUM) && g_strrstr(track->album, matches->album)) + ) { + */ + /* get the path */ char *path = strdup(track->ipod_path) ; itdb_filename_ipod2fs(path) ; @@ -280,58 +385,3 @@ void print_track(gpointer data, gpointer user_data) { return(r == str + strlen(str) - 1) ; } - void notify(const idevice_event_t *ev, void *user_data) { - enum idevice_event_type e = ev->event ; - const char * u = ev->udid ; - - switch(e) { - case IDEVICE_DEVICE_ADD : - printf("Device added\n") ; - break; - case IDEVICE_DEVICE_REMOVE : - printf("Device removed\n") ; - break; - default : - printf("Unknown idevice_event_type\n") ; - } - - printf("Device udid: %s with: %s\n", u, (char *)user_data) ; - } - - void test_imobiledevice() { - char **device_udids ; - int count ; - - char user_data[] = "Some user data" ; - - idevice_event_subscribe(¬ify, (void *)user_data) ; - - idevice_error_t err = idevice_get_device_list(&device_udids, &count) ; - - sleep(3) ; - - if(err == IDEVICE_E_SUCCESS) { - printf("Found %d ilibmobile devices.\n", count) ; - for(int i = 0 ; i < count ; i++) { - uint32_t handle ; - idevice_t device ; - - idevice_new(&device, device_udids[i]) ; - printf("Just called idevice_new()\n") ; - - idevice_get_handle(device, &handle) ; - printf("Just called idevice_get_handle()\n") ; - - //printf("%s with handle %d.\n", device_udids[i], handle) ; - idevice_free(device) ; - printf("Just called idevice_free()\n") ; - - } - } else { - printf("ilibmobiledevice error\n") ; - } - - - idevice_device_list_free(device_udids) ; - idevice_event_unsubscribe() ; - } diff --git a/lsipod.h b/lsipod.h index f1ab7a1..6897840 100644 --- a/lsipod.h +++ b/lsipod.h @@ -4,3 +4,9 @@ #define lsipod_VERSION_MINOR 1 #define MAX_NUM_MOUNTED_IPODS 32 + +#define MATCH_ARTIST 1 +#define MATCH_TITLE 2 +#define MATCH_ALBUM 4 + +//typedef int match_t ;