libmtp.c
来自「Media transfer protocol implementation o」· C语言 代码 · 共 2,016 行 · 第 1/5 页
C
2,016 行
free(track->album); if (track->genre != NULL) free(track->genre); if (track->date != NULL) free(track->date); if (track->filename != NULL) free(track->filename); free(track); return;}/** * This function retrieves the track metadata for a track * given by a unique ID. * @param device a pointer to the device to get the track metadata off. * @param trackid the unique ID of the track. * @param objectformat the object format of this track, so we know what it supports. * @param track a metadata set to fill in. */static void get_track_metadata(LIBMTP_mtpdevice_t *device, uint16_t objectformat, LIBMTP_track_t *track){ uint16_t ret; PTPParams *params = (PTPParams *) device->params; PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo; uint32_t i;#ifdef ENABLE_MTP_ENHANCED if (ptp_operation_issupported(params,PTP_OC_MTP_GetObjPropList) && !(ptp_usb->device_flags & DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST)) { MTPPropList *proplist = NULL; MTPPropList *prop; MTPPropList *tmpprop; /* * This should retrieve all properties for an object, but on devices * which are inherently broken it will not, so these need the * special flag DEVICE_FLAG_BROKEN_MTPGETOBJPROPLIST. */ ret = ptp_mtp_getobjectproplist(params, track->item_id, &proplist); prop = proplist; while (prop != NULL) { switch (prop->property) { case PTP_OPC_Name: if (prop->propval.str != NULL) track->title = strdup(prop->propval.str); else track->title = NULL; break; case PTP_OPC_Artist: if (prop->propval.str != NULL) track->artist = strdup(prop->propval.str); else track->artist = NULL; break; case PTP_OPC_Duration: track->duration = prop->propval.u32; break; case PTP_OPC_Track: track->tracknumber = prop->propval.u16; break; case PTP_OPC_Genre: if (prop->propval.str != NULL) track->genre = strdup(prop->propval.str); else track->genre = NULL; break; case PTP_OPC_AlbumName: if (prop->propval.str != NULL) track->album = strdup(prop->propval.str); else track->album = NULL; break; case PTP_OPC_OriginalReleaseDate: if (prop->propval.str != NULL) track->date = strdup(prop->propval.str); else track->date = NULL; break; // These are, well not so important. case PTP_OPC_SampleRate: track->samplerate = prop->propval.u32; break; case PTP_OPC_NumberOfChannels: track->nochannels = prop->propval.u16; break; case PTP_OPC_AudioWAVECodec: track->wavecodec = prop->propval.u32; break; case PTP_OPC_AudioBitRate: track->bitrate = prop->propval.u32; break; case PTP_OPC_BitRateType: track->bitratetype = prop->propval.u16; break; case PTP_OPC_Rating: track->rating = prop->propval.u16; break; case PTP_OPC_UseCount: track->usecount = prop->propval.u32; break; } tmpprop = prop; prop = prop->next; Destroy_MTP_Prop_Entry(tmpprop); } } else {#else {#endif uint16_t *props = NULL; uint32_t propcnt = 0; // First see which properties can be retrieved for this object format ret = ptp_mtp_getobjectpropssupported (params, map_libmtp_type_to_ptp_type(track->filetype), &propcnt, &props); if (ret != PTP_RC_OK) { // Just bail out for now, nothing is ever set. return; } else { for (i=0;i<propcnt;i++) { switch (props[i]) { case PTP_OPC_Name: track->title = get_string_from_object(device, track->item_id, PTP_OPC_Name); break; case PTP_OPC_Artist: track->artist = get_string_from_object(device, track->item_id, PTP_OPC_Artist); break; case PTP_OPC_Duration: track->duration = get_u32_from_object(device, track->item_id, PTP_OPC_Duration, 0); break; case PTP_OPC_Track: track->tracknumber = get_u16_from_object(device, track->item_id, PTP_OPC_Track, 0); break; case PTP_OPC_Genre: track->genre = get_string_from_object(device, track->item_id, PTP_OPC_Genre); break; case PTP_OPC_AlbumName: track->album = get_string_from_object(device, track->item_id, PTP_OPC_AlbumName); break; case PTP_OPC_OriginalReleaseDate: track->date = get_string_from_object(device, track->item_id, PTP_OPC_OriginalReleaseDate); break; // These are, well not so important. case PTP_OPC_SampleRate: track->samplerate = get_u32_from_object(device, track->item_id, PTP_OPC_SampleRate, 0); break; case PTP_OPC_NumberOfChannels: track->nochannels = get_u16_from_object(device, track->item_id, PTP_OPC_NumberOfChannels, 0); break; case PTP_OPC_AudioWAVECodec: track->wavecodec = get_u32_from_object(device, track->item_id, PTP_OPC_AudioWAVECodec, 0); break; case PTP_OPC_AudioBitRate: track->bitrate = get_u32_from_object(device, track->item_id, PTP_OPC_AudioBitRate, 0); break; case PTP_OPC_BitRateType: track->bitratetype = get_u16_from_object(device, track->item_id, PTP_OPC_BitRateType, 0); break; case PTP_OPC_Rating: track->rating = get_u16_from_object(device, track->item_id, PTP_OPC_Rating, 0); break; case PTP_OPC_UseCount: track->usecount = get_u32_from_object(device, track->item_id, PTP_OPC_UseCount, 0); break; } } free(props); } }}/** * THIS FUNCTION IS DEPRECATED. PLEASE UPDATE YOUR CODE IN ORDER * NOT TO USE IT. * @see LIBMTP_Get_Tracklisting_With_Callback() */LIBMTP_track_t *LIBMTP_Get_Tracklisting(LIBMTP_mtpdevice_t *device){ printf("WARNING: LIBMTP_Get_Tracklisting() is deprecated.\n"); printf("WARNING: please update your code to use LIBMTP_Get_Tracklisting_With_Callback()\n"); return LIBMTP_Get_Tracklisting_With_Callback(device, NULL, NULL);}/** * This returns a long list of all tracks available * on the current MTP device. Typical usage: * * <pre> * LIBMTP_track_t *tracklist; * * tracklist = LIBMTP_Get_Tracklisting(device, callback, data); * while (tracklist != NULL) { * LIBMTP_track_t *tmp; * * // Do something on each element in the list here... * tmp = tracklist; * tracklist = tracklist->next; * LIBMTP_destroy_track_t(tmp); * } * </pre> * * @param device a pointer to the device to get the track 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 tracks that can be followed using the <code>next</code> * field of the <code>LIBMTP_track_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_Trackmetadata() */LIBMTP_track_t *LIBMTP_Get_Tracklisting_With_Callback(LIBMTP_mtpdevice_t *device, LIBMTP_progressfunc_t const callback, void const * const data){ uint32_t i = 0; LIBMTP_track_t *retracks = NULL; LIBMTP_track_t *curtrack = 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_track_t *track; PTPObjectInfo oi; if (ptp_getobjectinfo(params, params->handles.Handler[i], &oi) == PTP_RC_OK) { // Ignore stuff we don't know how to handle... // TODO: get this list as an intersection of the sets // supported by the device and the from the device and // all known audio track files? if ( oi.ObjectFormat != PTP_OFC_WAV && oi.ObjectFormat != PTP_OFC_MP3 && oi.ObjectFormat != PTP_OFC_MTP_WMA && oi.ObjectFormat != PTP_OFC_MTP_OGG && oi.ObjectFormat != PTP_OFC_MTP_MP4 && oi.ObjectFormat != PTP_OFC_MTP_UndefinedAudio ) { // printf("Not a music track (format: %d), skipping...\n",oi.ObjectFormat); continue; } // Allocate a new track type track = LIBMTP_new_track_t(); // This is some sort of unique ID so we can keep track of the track. track->item_id = params->handles.Handler[i]; track->parent_id = oi.ParentObject; track->filetype = map_ptp_type_to_libmtp_type(oi.ObjectFormat); // Original file-specific properties track->filesize = oi.ObjectCompressedSize; if (oi.Filename != NULL) { track->filename = strdup(oi.Filename); } get_track_metadata(device, oi.ObjectFormat, track); // Add track to a list that will be returned afterwards. if (retracks == NULL) { retracks = track; curtrack = track; } else { curtrack->next = track; curtrack = track; } // 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 retracks;}/** * This function retrieves the metadata for a single track off * the device. * * Do not call this function repeatedly! The track handles are linearly * searched O(n) and the call may involve (slow) USB traffic, so use * <code>LIBMTP_Get_Tracklisting()</code> and cache the tracks, preferably * as an efficient data structure such as a hash list. * * @param device a pointer to the device to get the track metadata from. * @param trackid the object ID of the track that you want the metadata for. * @return a track metadata entry on success or NULL on failure. * @see LIBMTP_Get_Tracklisting() */LIBMTP_track_t *LIBMTP_Get_Trackmetadata(LIBMTP_mtpdevice_t *device, uint32_t const trackid){ 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++) { PTPObjectInfo oi; // Skip if this is not the track we want. if (params->handles.Handler[i] != trackid) { continue; } if (ptp_getobjectinfo(params, params->handles.Handler[i], &oi) == PTP_RC_OK) { LIBMTP_track_t *track; // Ignore stuff we don't know how to handle... if ( oi.ObjectFormat != PTP_OFC_WAV && oi.ObjectFormat != PTP_OFC_MP3 && oi.ObjectFormat != PTP_OFC_MTP_WMA && oi.ObjectFormat != PTP_OFC_MTP_OGG && oi.ObjectFormat != PTP_OFC_MTP_MP4 && oi.ObjectFormat != PTP_OFC_MTP_UndefinedAudio ) { return NULL; } // Allocate a new track type track = LIBMTP_new_track_t(); // This is some sort of unique ID so we can keep track of the track. track->item_id = params->handles.Handler[i]; track->parent_id = oi.ParentObject; track->filetype = map_ptp_type_to_libmtp_type(oi.ObjectFormat); // Original file-specific properties track->filesize = oi.ObjectCompressedSize; if (oi.Filename != NULL) { track->filename = strdup(oi.Filename); } get_track_metadata(device, oi.ObjectFormat, track); return track; } else { return NULL; } } return NULL;}/** * This gets a file off the device to a local file identified * by a filename. * @param device a pointer to the device to get the track from. * @param id the file ID of the file to retrieve. * @param path a filename to use for the retrieved file. * @param callback a progress indicator function or NULL to ignore. * @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 0 if the transfer was successful, any other value means * failure. * @see LIBMTP_Get_File_To_File_Descriptor() */int LIBMTP_Get_File_To_File(LIBMTP_mtpdevice_t *device, uint32_t const id, char const * const path, LIBMTP_progressfunc_t const callback, void const * const data){ int fd = -1; int ret; // Sanity check if (path == NULL) { printf("LIBMTP_Get_File_To_File(): Bad arguments, path was NULL\n"); return -1; } // Open file#ifdef __WIN32__#ifdef USE_WINDOWS_IO_H if ( (fd = _open(path, O_RDWR|O_CREAT|O_TRUNC|O_BINARY,_S_IREAD)) == -1 ) {#else if ( (fd = open(path, O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IRWXU|S_IRGRP)) == -1 ) {#endif#else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?