コード例 #1
0
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);
}
コード例 #2
0
ファイル: detect.c プロジェクト: reverendhomer/libmtp
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, &sectime);
        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;
}