static void download_track (RBMtpThread *thread, RBMtpThreadTask *task) { LIBMTP_file_t *fileinfo; LIBMTP_error_t *stack; GError *error = NULL; GFile *dir; RBMtpDownloadCallback cb = (RBMtpDownloadCallback) task->callback; /* first, check there's enough space to copy it */ fileinfo = LIBMTP_Get_Filemetadata (thread->device, task->track_id); if (fileinfo == NULL) { stack = LIBMTP_Get_Errorstack (thread->device); rb_debug ("unable to get track metadata for %u: %s", task->track_id, stack->error_text); error = g_error_new (RB_MTP_THREAD_ERROR, RB_MTP_THREAD_ERROR_GET_TRACK, _("Unable to copy file from MTP device: %s"), stack->error_text); LIBMTP_Clear_Errorstack (thread->device); cb (task->track_id, NULL, error, task->user_data); g_error_free (error); return; } if (task->filename[0] == '\0') { dir = g_file_new_for_path (g_get_tmp_dir ()); } else { GFile *file = g_file_new_for_path (task->filename); dir = g_file_get_parent (file); g_object_unref (file); } rb_debug ("checking for %" G_GINT64_FORMAT " bytes available", fileinfo->filesize); if (rb_check_dir_has_space (dir, fileinfo->filesize) == FALSE) { char *dpath = g_file_get_path (dir); rb_debug ("not enough space in %s", dpath); error = g_error_new (RB_MTP_THREAD_ERROR, RB_MTP_THREAD_ERROR_NO_SPACE, _("Not enough space in %s"), dpath); g_free (dpath); } LIBMTP_destroy_file_t (fileinfo); g_object_unref (dir); if (error != NULL) { rb_debug ("bailing out due to error: %s", error->message); cb (task->track_id, NULL, error, task->user_data); g_error_free (error); return; } if (task->filename[0] == '\0') { /* download to a temporary file */ int fd; GError *tmperror = NULL; g_free (task->filename); fd = g_file_open_tmp ("rb-mtp-temp-XXXXXX", &task->filename, &tmperror); if (fd == -1) { rb_debug ("unable to open temporary file: %s", tmperror->message); error = g_error_new (RB_MTP_THREAD_ERROR, RB_MTP_THREAD_ERROR_TEMPFILE, _("Unable to open temporary file: %s"), tmperror->message); g_error_free (tmperror); cb (task->track_id, NULL, error, task->user_data); g_error_free (error); return; } else { rb_debug ("downloading track %u to file descriptor %d", task->track_id, fd); if (LIBMTP_Get_Track_To_File_Descriptor (thread->device, task->track_id, fd, NULL, NULL)) { stack = LIBMTP_Get_Errorstack (thread->device); rb_debug ("unable to retrieve track %u: %s", task->track_id, stack->error_text); error = g_error_new (RB_MTP_THREAD_ERROR, RB_MTP_THREAD_ERROR_GET_TRACK, _("Unable to copy file from MTP device: %s"), stack->error_text); LIBMTP_Clear_Errorstack (thread->device); cb (task->track_id, NULL, error, task->user_data); g_error_free (error); close (fd); remove (task->filename); return; } rb_debug ("done downloading track"); close (fd); } } else { if (LIBMTP_Get_Track_To_File (thread->device, task->track_id, task->filename, NULL, NULL)) { stack = LIBMTP_Get_Errorstack (thread->device); error = g_error_new (RB_MTP_THREAD_ERROR, RB_MTP_THREAD_ERROR_GET_TRACK, _("Unable to copy file from MTP device: %s"), stack->error_text); LIBMTP_Clear_Errorstack (thread->device); cb (task->track_id, NULL, error, task->user_data); g_error_free (error); return; } } cb (task->track_id, task->filename, NULL, task->user_data); }
int main (int argc, char **argv) { LIBMTP_raw_device_t * rawdevices; int numrawdevices; LIBMTP_error_number_t err; int i; int opt; extern int optind; extern char *optarg; while ((opt = getopt(argc, argv, "d")) != -1 ) { switch (opt) { case 'd': LIBMTP_Set_Debug(LIBMTP_DEBUG_PTP | LIBMTP_DEBUG_DATA); break; } } argc -= optind; argv += optind; LIBMTP_Init(); fprintf(stdout, "libmtp version: " LIBMTP_VERSION_STRING "\n\n"); fprintf(stdout, "Listing raw device(s)\n"); err = LIBMTP_Detect_Raw_Devices(&rawdevices, &numrawdevices); switch(err) { case LIBMTP_ERROR_NO_DEVICE_ATTACHED: fprintf(stdout, " No raw devices found.\n"); return 0; case LIBMTP_ERROR_CONNECTING: fprintf(stderr, "Detect: There has been an error connecting. Exiting\n"); return 1; case LIBMTP_ERROR_MEMORY_ALLOCATION: fprintf(stderr, "Detect: Encountered a Memory Allocation Error. Exiting\n"); return 1; case LIBMTP_ERROR_NONE: { int i; fprintf(stdout, " Found %d device(s):\n", numrawdevices); for (i = 0; i < numrawdevices; i++) { if (rawdevices[i].device_entry.vendor != NULL || rawdevices[i].device_entry.product != NULL) { fprintf(stdout, " %s: %s (%04x:%04x) @ bus %d, dev %d\n", rawdevices[i].device_entry.vendor, rawdevices[i].device_entry.product, rawdevices[i].device_entry.vendor_id, rawdevices[i].device_entry.product_id, rawdevices[i].bus_location, rawdevices[i].devnum); } else { fprintf(stdout, " %04x:%04x @ bus %d, dev %d\n", rawdevices[i].device_entry.vendor_id, rawdevices[i].device_entry.product_id, rawdevices[i].bus_location, rawdevices[i].devnum); } } } break; case LIBMTP_ERROR_GENERAL: default: fprintf(stderr, "Unknown connection error.\n"); return 1; } /* Iterate over connected MTP devices */ fprintf(stdout, "Attempting to connect device(s)\n"); for (i = 0; i < numrawdevices; i++) { LIBMTP_mtpdevice_t *device; LIBMTP_devicestorage_t *storage; char *friendlyname; char *syncpartner; char *sectime; char *devcert; uint16_t *filetypes; uint16_t filetypes_len; uint8_t maxbattlevel; uint8_t currbattlevel; int ret; device = LIBMTP_Open_Raw_Device_Uncached(&rawdevices[i]); if (device == NULL) { fprintf(stderr, "Unable to open raw device %d\n", i); continue; } LIBMTP_Dump_Errorstack(device); LIBMTP_Clear_Errorstack(device); LIBMTP_Dump_Device_Info(device); printf("MTP-specific device properties:\n"); // The friendly name friendlyname = LIBMTP_Get_Friendlyname(device); if (friendlyname == NULL) { fprintf(stdout, " Friendly name: (NULL)\n"); } else { fprintf(stdout, " Friendly name: %s\n", friendlyname); free(friendlyname); } syncpartner = LIBMTP_Get_Syncpartner(device); if (syncpartner == NULL) { fprintf(stdout, " Synchronization partner: (NULL)\n"); } else { fprintf(stdout, " Synchronization partner: %s\n", syncpartner); free(syncpartner); } // Some battery info ret = LIBMTP_Get_Batterylevel(device, &maxbattlevel, &currbattlevel); if (ret == 0) { fprintf(stdout, " Battery level %d of %d (%d%%)\n",currbattlevel, maxbattlevel, (int) ((float) currbattlevel/ (float) maxbattlevel * 100.0)); } else { // Silently ignore. Some devices does not support getting the // battery level. LIBMTP_Clear_Errorstack(device); } ret = LIBMTP_Get_Supported_Filetypes(device, &filetypes, &filetypes_len); if (ret == 0) { uint16_t i; printf("libmtp supported (playable) filetypes:\n"); for (i = 0; i < filetypes_len; i++) { fprintf(stdout, " %s\n", LIBMTP_Get_Filetype_Description(filetypes[i])); } } else { LIBMTP_Dump_Errorstack(device); LIBMTP_Clear_Errorstack(device); } // Secure time XML fragment ret = LIBMTP_Get_Secure_Time(device, §ime); if (ret == 0 && sectime != NULL) { fprintf(stdout, "\nSecure Time:\n%s\n", sectime); free(sectime); } else { // Silently ignore - there may be devices not supporting secure time. LIBMTP_Clear_Errorstack(device); } // Device certificate XML fragment if (rawdevices[i].device_entry.vendor_id == 0x041e) { /* * This code is currently disabled except for vendors we * know does support it: all devices say that * they support getting a device certificate but a lot of * them obviously doesn't, instead they crash when you try * to obtain it. */ ret = LIBMTP_Get_Device_Certificate(device, &devcert); if (ret == 0 && devcert != NULL) { fprintf(stdout, "\nDevice Certificate:\n%s\n", devcert); free(devcert); } else { fprintf(stdout, "Unable to acquire device certificate, perhaps this device " "does not support this\n"); LIBMTP_Dump_Errorstack(device); LIBMTP_Clear_Errorstack(device); } } /* Try to get Media player device info XML file... */ /* Loop over storages */ for (storage = device->storage; storage != 0; storage = storage->next) { LIBMTP_file_t *files; /* Get file listing for the root directory, no other dirs */ files = LIBMTP_Get_Files_And_Folders(device, storage->id, 0); if (files != NULL) { LIBMTP_file_t *file, *tmp; file = files; while (file != NULL) { if (!strcmp(file->filename, "WMPInfo.xml") || !strcmp(file->filename, "WMPinfo.xml") || !strcmp(file->filename, "default-capabilities.xml")) { if (file->item_id != 0) { /* Dump this file */ FILE *xmltmp = tmpfile(); int tmpfiledescriptor = fileno(xmltmp); if (tmpfiledescriptor != -1) { int ret = LIBMTP_Get_Track_To_File_Descriptor(device, file->item_id, tmpfiledescriptor, NULL, NULL); if (ret == 0) { uint8_t *buf = NULL; uint32_t readbytes; buf = malloc(XML_BUFSIZE); if (buf == NULL) { printf("Could not allocate %08x bytes...\n", XML_BUFSIZE); LIBMTP_Dump_Errorstack(device); LIBMTP_Clear_Errorstack(device); free(rawdevices); return 1; } lseek(tmpfiledescriptor, 0, SEEK_SET); readbytes = read(tmpfiledescriptor, (void*) buf, XML_BUFSIZE); if (readbytes >= 2 && readbytes < XML_BUFSIZE) { fprintf(stdout, "\n%s file contents:\n", file->filename); dump_xml_fragment(buf, readbytes); } else { perror("Unable to read file"); LIBMTP_Dump_Errorstack(device); LIBMTP_Clear_Errorstack(device); } free(buf); } else { LIBMTP_Dump_Errorstack(device); LIBMTP_Clear_Errorstack(device); } fclose(xmltmp); } } } tmp = file; file = file->next; LIBMTP_destroy_file_t(tmp); } } } LIBMTP_Release_Device(device); } /* End For Loop */ free(rawdevices); printf("OK.\n"); return 0; }