libmtp.c
来自「Media transfer protocol implementation o」· C语言 代码 · 共 2,016 行 · 第 1/5 页
C
2,016 行
/** * Helper function to extract a unicode property off a device. * This is the standard way of retrieveing unicode device * properties as described by the PTP spec. * @param device a pointer to the device to get the property from. * @param unicstring a pointer to a pointer that will hold the * property after this call is completed. * @param property the property to retrieve. * @return 0 on success, any other value means failure. */static int get_device_unicode_property(LIBMTP_mtpdevice_t *device, char **unicstring, uint16_t property){ PTPPropertyValue propval; PTPParams *params = (PTPParams *) device->params; uint16_t *tmp; int i; if (!ptp_property_issupported(params, property)) { return -1; } // Unicode strings are 16bit unsigned integer arrays. if (ptp_getdevicepropvalue(params, property, &propval, PTP_DTC_AUINT16) != PTP_RC_OK) { return -1; } // Extract the actual array. // printf("Array of %d elements\n", propval.a.count); tmp = malloc((propval.a.count + 1)*sizeof(uint16_t)); for (i = 0; i < propval.a.count; i++) { tmp[i] = propval.a.v[i].u16; // printf("%04x ", tmp[i]); } tmp[propval.a.count] = 0x0000U; free(propval.a.v); *unicstring = utf16_to_utf8(device, tmp); free(tmp); return 0;}/** * This function returns the secure time as an XML document string from * the device. * @param device a pointer to the device to get the secure time for. * @param sectime the secure time string as an XML document or NULL if the call * failed or the secure time property is not supported. This string * must be <code>free()</code>:ed by the caller after use. * @return 0 on success, any other value means failure. */int LIBMTP_Get_Secure_Time(LIBMTP_mtpdevice_t *device, char ** const sectime){ return get_device_unicode_property(device, sectime, PTP_DPC_MTP_SecureTime);}/** * This function returns the device (public key) certificate as an * XML document string from the device. * @param device a pointer to the device to get the device certificate for. * @param devcert the device certificate as an XML string or NULL if the call * failed or the device certificate property is not supported. This * string must be <code>free()</code>:ed by the caller after use. * @return 0 on success, any other value means failure. */int LIBMTP_Get_Device_Certificate(LIBMTP_mtpdevice_t *device, char ** const devcert){ return get_device_unicode_property(device, devcert, PTP_DPC_MTP_DeviceCertificate);}/** * This function retrieves a list of supported file types, i.e. the file * types that this device claims it supports, e.g. audio file types that * the device can play etc. This list is mitigated to * inlcude the file types that libmtp can handle, i.e. it will not list * filetypes that libmtp will handle internally like playlists and folders. * @param device a pointer to the device to get the filetype capabilities for. * @param filetypes a pointer to a pointer that will hold the list of * supported filetypes if the call was successful. This list must * be <code>free()</code>:ed by the caller after use. * @param length a pointer to a variable that will hold the length of the * list of supported filetypes if the call was successful. * @return 0 on success, any other value means failure. * @see LIBMTP_Get_Filetype_Description() */int LIBMTP_Get_Supported_Filetypes(LIBMTP_mtpdevice_t *device, uint16_t ** const filetypes, uint16_t * const length){ PTPParams *params = (PTPParams *) device->params; uint16_t *localtypes; uint16_t localtypelen; uint32_t i; // This is more memory than needed if there are unknown types, but what the heck. localtypes = (uint16_t *) malloc(params->deviceinfo.ImageFormats_len * sizeof(uint16_t)); localtypelen = 0; for (i=0;i<params->deviceinfo.ImageFormats_len;i++) { uint16_t localtype = map_ptp_type_to_libmtp_type(params->deviceinfo.ImageFormats[i]); if (localtype != LIBMTP_FILETYPE_UNKNOWN) { localtypes[localtypelen] = localtype; localtypelen++; } } *filetypes = localtypes; *length = localtypelen; return 0;}/** * This creates a new file metadata structure and allocates memory * for it. Notice that if you add strings to this structure they * will be freed by the corresponding <code>LIBMTP_destroy_file_t</code> * operation later, so be careful of using strdup() when assigning * strings, e.g.: * * <pre> * LIBMTP_file_t *file = LIBMTP_new_file_t(); * file->filename = strdup(namestr); * .... * LIBMTP_destroy_file_t(file); * </pre> * * @return a pointer to the newly allocated metadata structure. * @see LIBMTP_destroy_file_t() */LIBMTP_file_t *LIBMTP_new_file_t(void){ LIBMTP_file_t *new = (LIBMTP_file_t *) malloc(sizeof(LIBMTP_file_t)); if (new == NULL) { return NULL; } new->filename = NULL; new->filesize = 0; new->filetype = LIBMTP_FILETYPE_UNKNOWN; new->next = NULL; return new;}/** * This destroys a file metadata structure and deallocates the memory * used by it, including any strings. Never use a file metadata * structure again after calling this function on it. * @param file the file metadata to destroy. * @see LIBMTP_new_file_t() */void LIBMTP_destroy_file_t(LIBMTP_file_t *file){ if (file == NULL) { return; } if (file->filename != NULL) free(file->filename); free(file); return;}/*** THIS FUNCTION IS DEPRECATED. PLEASE UPDATE YOUR CODE IN ORDER * NOT TO USE IT. * @see LIBMTP_Get_Filelisting_With_Callback() */LIBMTP_file_t *LIBMTP_Get_Filelisting(LIBMTP_mtpdevice_t *device){ printf("WARNING: LIBMTP_Get_Filelisting() is deprecated.\n"); printf("WARNING: please update your code to use LIBMTP_Get_Filelisting_With_Callback()\n"); return LIBMTP_Get_Filelisting_With_Callback(device, NULL, NULL);}/** * This returns a long list of all files available * on the current MTP device. Typical usage: * * <pre> * LIBMTP_file_t *filelist; * * filelist = LIBMTP_Get_Filelisting_With_Callback(device, callback, data); * while (filelist != NULL) { * LIBMTP_file_t *tmp; * * // Do something on each element in the list here... * tmp = filelist; * filelist = filelist->next; * LIBMTP_destroy_file_t(tmp); * } * </pre> * * @param device a pointer to the device to get the file listing for. * @param callback a function to be called during the tracklisting retrieveal * for displaying progress bars etc, or NULL if you don't want * any callbacks. * @param data a user-defined pointer that is passed along to * the <code>progress</code> function in order to * pass along some user defined data to the progress * updates. If not used, set this to NULL. * @return a list of files that can be followed using the <code>next</code> * field of the <code>LIBMTP_file_t</code> data structure. * Each of the metadata tags must be freed after use, and may * contain only partial metadata information, i.e. one or several * fields may be NULL or 0. * @see LIBMTP_Get_Filemetadata() */LIBMTP_file_t *LIBMTP_Get_Filelisting_With_Callback(LIBMTP_mtpdevice_t *device, LIBMTP_progressfunc_t const callback, void const * const data){ uint32_t i = 0; LIBMTP_file_t *retfiles = NULL; LIBMTP_file_t *curfile = NULL; PTPParams *params = (PTPParams *) device->params; // Get all the handles if we haven't already done that if (params->handles.Handler == NULL) { flush_handles(device); } for (i = 0; i < params->handles.n; i++) { if (callback != NULL) callback(i, params->handles.n, data); LIBMTP_file_t *file; PTPObjectInfo oi; if (ptp_getobjectinfo(params, params->handles.Handler[i], &oi) == PTP_RC_OK) { if (oi.ObjectFormat == PTP_OFC_Association) { // MTP use thesis object format for folders which means // these "files" will turn up on a folder listing instead. continue; } // Allocate a new file type file = LIBMTP_new_file_t(); file->parent_id = oi.ParentObject; // Set the filetype file->filetype = map_ptp_type_to_libmtp_type(oi.ObjectFormat); // Original file-specific properties file->filesize = oi.ObjectCompressedSize; if (oi.Filename != NULL) { file->filename = strdup(oi.Filename); } // This is some sort of unique ID so we can keep track of the track. file->item_id = params->handles.Handler[i]; // Add track to a list that will be returned afterwards. if (retfiles == NULL) { retfiles = file; curfile = file; } else { curfile->next = file; curfile = file; } // Call listing callback // double progressPercent = (double)i*(double)100.0 / (double)params->handles.n; } else { printf("LIBMTP panic: Found a bad handle, trying to ignore it.\n"); } } // Handle counting loop return retfiles;}/** * This function retrieves the metadata for a single file off * the device. * * Do not call this function repeatedly! The file handles are linearly * searched O(n) and the call may involve (slow) USB traffic, so use * <code>LIBMTP_Get_Filelisting()</code> and cache the file, preferably * as an efficient data structure such as a hash list. * * @param device a pointer to the device to get the file metadata from. * @param fileid the object ID of the file that you want the metadata for. * @return a metadata entry on success or NULL on failure. * @see LIBMTP_Get_Filelisting() */LIBMTP_file_t *LIBMTP_Get_Filemetadata(LIBMTP_mtpdevice_t *device, uint32_t const fileid){ uint32_t i = 0; PTPParams *params = (PTPParams *) device->params; // Get all the handles if we haven't already done that if (params->handles.Handler == NULL) { flush_handles(device); } for (i = 0; i < params->handles.n; i++) { LIBMTP_file_t *file; PTPObjectInfo oi; // Is this the file we're looking for? if (params->handles.Handler[i] != fileid) { continue; } if (ptp_getobjectinfo(params, params->handles.Handler[i], &oi) == PTP_RC_OK) { if (oi.ObjectFormat == PTP_OFC_Association) { // MTP use thesis object format for folders which means // these "files" will turn up on a folder listing instead. return NULL; } // Allocate a new file type file = LIBMTP_new_file_t(); file->parent_id = oi.ParentObject; // Set the filetype file->filetype = map_ptp_type_to_libmtp_type(oi.ObjectFormat); // Original file-specific properties file->filesize = oi.ObjectCompressedSize; if (oi.Filename != NULL) { file->filename = strdup(oi.Filename); } // This is some sort of unique ID so we can keep track of the track. file->item_id = params->handles.Handler[i]; return file; } else { return NULL; } } return NULL;}/** * This creates a new track metadata structure and allocates memory * for it. Notice that if you add strings to this structure they * will be freed by the corresponding <code>LIBMTP_destroy_track_t</code> * operation later, so be careful of using strdup() when assigning * strings, e.g.: * * <pre> * LIBMTP_track_t *track = LIBMTP_new_track_t(); * track->title = strdup(titlestr); * .... * LIBMTP_destroy_track_t(track); * </pre> * * @return a pointer to the newly allocated metadata structure. * @see LIBMTP_destroy_track_t() */LIBMTP_track_t *LIBMTP_new_track_t(void){ LIBMTP_track_t *new = (LIBMTP_track_t *) malloc(sizeof(LIBMTP_track_t)); if (new == NULL) { return NULL; } new->title = NULL; new->artist = NULL; new->album = NULL; new->genre = NULL; new->date = NULL; new->filename = NULL; new->duration = 0; new->tracknumber = 0; new->filesize = 0; new->filetype = LIBMTP_FILETYPE_UNKNOWN; new->samplerate = 0; new->nochannels = 0; new->wavecodec = 0; new->bitrate = 0; new->bitratetype = 0; new->rating = 0; new->usecount = 0; new->next = NULL; return new;}/** * This destroys a track metadata structure and deallocates the memory * used by it, including any strings. Never use a track metadata * structure again after calling this function on it. * @param track the track metadata to destroy. * @see LIBMTP_new_track_t() */void LIBMTP_destroy_track_t(LIBMTP_track_t *track){ if (track == NULL) { return; } if (track->title != NULL) free(track->title); if (track->artist != NULL) free(track->artist); if (track->album != NULL)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?