void recursive_file_tree(LIBMTP_mtpdevice_t *device, LIBMTP_devicestorage_t *storage, uint32_t leaf, int depth) { LIBMTP_file_t *files; LIBMTP_file_t *file; files = LIBMTP_Get_Files_And_Folders(device, storage->id, leaf); if (files == NULL) { return; } /* Iterate over the filelisting */ for (file = files; file != NULL; file = file->next) { int i; /* Indent */ for (i = 0; i < depth; i++) { printf(" "); } printf("%u %s\n", file->item_id, file->filename); if (file->filetype == LIBMTP_FILETYPE_FOLDER) { recursive_file_tree(device, storage, file->item_id, depth+2); } } }
static int recursive_get_files(LIBMTP_mtpdevice_t *dev, uint32_t storage_id, uint32_t parent_id, PyObject *ans, PyObject *errs, PyObject *callback, unsigned int level) { LIBMTP_file_t *f, *files; PyObject *entry, *r; int ok = 1, recurse; Py_BEGIN_ALLOW_THREADS; files = LIBMTP_Get_Files_And_Folders(dev, storage_id, parent_id); Py_END_ALLOW_THREADS; if (files == NULL) return ok; for (f = files; ok && f != NULL; f = f->next) { entry = build_file_metadata(f, storage_id); if (entry == NULL) { ok = 0; } else { r = PyObject_CallFunction(callback, "OI", entry, level); recurse = (r != NULL && PyObject_IsTrue(r)) ? 1 : 0; Py_XDECREF(r); if (PyList_Append(ans, entry) != 0) { ok = 0; } Py_DECREF(entry); } if (ok && recurse && f->filetype == LIBMTP_FILETYPE_FOLDER) { if (!recursive_get_files(dev, storage_id, f->item_id, ans, errs, callback, level+1)) { ok = 0; } } } // Release memory f = files; while (f != NULL) { files = f; f = f->next; LIBMTP_destroy_file_t(files); } return ok; }
const TypeDir *MTPDevice::dirFetchContent(std::string path) { if (!m_root_dir.isFetched()) { for (LIBMTP_devicestorage_t *s = m_device->storage; s; s = s->next) { m_root_dir.addDir(TypeDir(s_root_node, 0, s->id, std::string(s->StorageDescription))); m_root_dir.setFetched(); } } if (m_root_dir.dirCount() == 1) path = '/' + m_root_dir.dirs().begin()->name() + path; if (path == "/") return &m_root_dir; std::string member; std::istringstream ss(path); TypeDir *dir = &m_root_dir; while (std::getline(ss, member, '/')) { if (member.empty()) continue; const TypeDir *tmp = dir->dir(member); if (!tmp && !dir->isFetched()) { criticalEnter(); LIBMTP_file_t *content = LIBMTP_Get_Files_And_Folders( m_device, dir->storageid(), dir->id()); criticalLeave(); for (LIBMTP_file_t *f = content; f; f = f->next) { if (f->filetype == LIBMTP_FILETYPE_FOLDER) dir->addDir(TypeDir(f)); else dir->addFile(TypeFile(f)); } LIBMTP_Free_Files_And_Folders(&content); dir->setFetched(); tmp = dir->dir(member); } if (!tmp) return nullptr; dir = const_cast<TypeDir*>(tmp); } if (dir->isFetched()) return dir; criticalEnter(); dir->setFetched(); LIBMTP_file_t *content = LIBMTP_Get_Files_And_Folders( m_device, dir->storageid(), dir->id()); criticalLeave(); for (LIBMTP_file_t *f = content; f; f = f->next) { if (f->filetype == LIBMTP_FILETYPE_FOLDER) dir->addDir(TypeDir(f)); else dir->addFile(TypeFile(f)); } LIBMTP_Free_Files_And_Folders(&content); return dir; }
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; }