libmtp.c
来自「Media transfer protocol implementation o」· C语言 代码 · 共 2,016 行 · 第 1/5 页
C
2,016 行
/** * \file libmtp.c * This file provides an interface "glue" to the underlying * PTP implementation from libgphoto2. It uses some local * code to convert from/to UTF-8 (stored in unicode.c/.h) * and some small utility functions, mainly for debugging * (stored in util.c/.h). * * The three PTP files (ptp.c, ptp.h and ptp-pack.c) are * plain copied from the libhphoto2 codebase. * * The files libusb-glue.c/.h are just what they say: an * interface to libusb for the actual, physical USB traffic. */#include "libmtp.h"#include "unicode.h"#include "ptp.h"#include "libusb-glue.h"#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#ifdef _MSC_VER // For MSVC++#define USE_WINDOWS_IO_H#include <io.h>#endif/* Enable enhanced MTP commands */#define ENABLE_MTP_ENHANCED/* * On MacOS (Darwin) and *BSD we're not using glibc, but libiconv. * glibc knows that UCS-2 is to be in the local machine endianness, * whereas libiconv does not. So we construct this macro to get * things right. Reportedly, glibc 2.1.3 has a bug so that UCS-2 * is always bigendian though, we would need to work around that * too... */#ifndef __GLIBC__#define UCS_2_INTERNAL "UCS-2-INTERNAL"#else#if (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1 )#error "Too old glibc. This versions iconv() implementation cannot be trusted."#endif#define UCS_2_INTERNAL "UCS-2"#endif/* * This is a mapping between libmtp internal MTP filetypes and * the libgphoto2/PTP equivalent defines. We need this because * otherwise the libmtp.h device has to be dependent on ptp.h * to be installed too, and we don't want that. *///typedef struct filemap_struct filemap_t;typedef struct filemap_struct { char *description; /**< Text description for the file type */ LIBMTP_filetype_t id; /**< LIBMTP internal type for the file type */ uint16_t ptp_id; /**< PTP ID for the filetype */ struct filemap_struct *next;} filemap_t;// Global variables// This holds the global filetype mapping tablestatic filemap_t *filemap = NULL;/* * Forward declarations of local (static) functions. */static int register_filetype(char const * const description, LIBMTP_filetype_t const id, uint16_t const ptp_id);static void init_filemap();static void flush_handles(LIBMTP_mtpdevice_t *device);static int check_if_file_fits(LIBMTP_mtpdevice_t *device, uint64_t const filesize);static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype);static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype);static int get_device_unicode_property(LIBMTP_mtpdevice_t *device, char **unicstring, uint16_t property);static char *get_string_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id);static uint32_t get_u32_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id, uint16_t const attribute_id, uint32_t const value_default);static uint16_t get_u16_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id, uint16_t const value_default);static uint8_t get_u8_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id, uint8_t const value_default);static int set_object_string(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id, char const * const string);static int set_object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id, uint32_t const value);static int set_object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id, uint16_t const value);static int set_object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id, uint8_t const value);static void get_track_metadata(LIBMTP_mtpdevice_t *device, uint16_t objectformat, LIBMTP_track_t *track);static int create_new_abstract_list(LIBMTP_mtpdevice_t *device, char const * const name, uint32_t const parenthandle, uint16_t const objectformat, char const * const suffix, uint32_t * const newid, uint32_t const * const tracks, uint32_t const no_tracks);static MTPPropList *New_MTP_Prop_Entry();static void Destroy_MTP_Prop_Entry(MTPPropList *prop);/** * Create a new file mapping entry * @return a newly allocated filemapping entry. */static filemap_t *new_filemap_entry(){ filemap_t *filemap; filemap = (filemap_t *)malloc(sizeof(filemap_t)); if( filemap != NULL ) { filemap->description = NULL; filemap->id = LIBMTP_FILETYPE_UNKNOWN; filemap->ptp_id = PTP_OFC_Undefined; filemap->next = NULL; } return filemap;}/** * Register an MTP or PTP filetype for data retrieval * * @param description Text description of filetype * @param id libmtp internal filetype id * @param ptp_id PTP filetype id * @return 0 for success any other value means error.*/static int register_filetype(char const * const description, LIBMTP_filetype_t const id, uint16_t const ptp_id){ filemap_t *new = NULL, *current; // Has this LIBMTP filetype been registered before ? current = filemap; while (current != NULL) { if(current->id == id) { break; } current = current->next; } // Create the entry if(current == NULL) { new = new_filemap_entry(); if(new == NULL) { return 1; } new->id = id; if(description != NULL) { new->description = strdup(description); } new->ptp_id = ptp_id; // Add the entry to the list if(filemap == NULL) { filemap = new; } else { current = filemap; while (current->next != NULL ) current=current->next; current->next = new; } // Update the existing entry } else { if (current->description != NULL) { free(current->description); } current->description = NULL; if(description != NULL) { current->description = strdup(description); } current->ptp_id = ptp_id; } return 0;}static void init_filemap(){ register_filetype("RIFF WAVE file", LIBMTP_FILETYPE_WAV, PTP_OFC_WAV); register_filetype("ISO MPEG Audio Layer 3", LIBMTP_FILETYPE_MP3, PTP_OFC_MP3); register_filetype("Microsoft Windows Media Audio", LIBMTP_FILETYPE_WMA, PTP_OFC_MTP_WMA); register_filetype("Ogg container format", LIBMTP_FILETYPE_OGG, PTP_OFC_MTP_OGG); register_filetype("Audible.com Audio Codec", LIBMTP_FILETYPE_AUDIBLE, PTP_OFC_MTP_AudibleCodec); register_filetype("Advanced Acoustic Coding", LIBMTP_FILETYPE_MP4, PTP_OFC_MTP_MP4); register_filetype("Undefined audio file", LIBMTP_FILETYPE_UNDEF_AUDIO, PTP_OFC_MTP_UndefinedAudio); register_filetype("Microsoft Windows Media Video", LIBMTP_FILETYPE_WMV, PTP_OFC_MTP_WMV); register_filetype("Audio Video Interleave", LIBMTP_FILETYPE_AVI, PTP_OFC_AVI); register_filetype("MPEG video stream", LIBMTP_FILETYPE_MPEG, PTP_OFC_MPEG); register_filetype("Microsoft Advanced Systems Format", LIBMTP_FILETYPE_ASF, PTP_OFC_ASF); register_filetype("Apple Quicktime container format", LIBMTP_FILETYPE_QT, PTP_OFC_QT); register_filetype("Undefined video file", LIBMTP_FILETYPE_UNDEF_VIDEO, PTP_OFC_MTP_UndefinedVideo); register_filetype("JPEG file", LIBMTP_FILETYPE_JPEG, PTP_OFC_EXIF_JPEG); register_filetype("JFIF file", LIBMTP_FILETYPE_JFIF, PTP_OFC_JFIF); register_filetype("TIFF bitmap file", LIBMTP_FILETYPE_TIFF, PTP_OFC_TIFF); register_filetype("BMP bitmap file", LIBMTP_FILETYPE_BMP, PTP_OFC_BMP); register_filetype("GIF bitmap file", LIBMTP_FILETYPE_GIF, PTP_OFC_GIF); register_filetype("PICT bitmap file", LIBMTP_FILETYPE_PICT, PTP_OFC_PICT); register_filetype("Portable Network Graphics", LIBMTP_FILETYPE_PNG, PTP_OFC_PNG); register_filetype("Microsoft Windows Image Format", LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT, PTP_OFC_MTP_WindowsImageFormat); register_filetype("VCalendar version 1", LIBMTP_FILETYPE_VCALENDAR1, PTP_OFC_MTP_vCalendar1); register_filetype("VCalendar version 2", LIBMTP_FILETYPE_VCALENDAR2, PTP_OFC_MTP_vCalendar2); register_filetype("VCard version 2", LIBMTP_FILETYPE_VCARD2, PTP_OFC_MTP_vCard2); register_filetype("VCard version 3", LIBMTP_FILETYPE_VCARD3, PTP_OFC_MTP_vCard3); register_filetype("Undefined Windows executable file", LIBMTP_FILETYPE_WINEXEC, PTP_OFC_MTP_UndefinedWindowsExecutable); register_filetype("Text file", LIBMTP_FILETYPE_TEXT, PTP_OFC_Text); register_filetype("HTML file", LIBMTP_FILETYPE_HTML, PTP_OFC_HTML); register_filetype("Undefined filetype", LIBMTP_FILETYPE_UNKNOWN, PTP_OFC_Undefined);}/** * Returns the PTP filetype that maps to a certain libmtp internal file type. * @param intype the MTP library interface type * @return the PTP (libgphoto2) interface type */static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype){ filemap_t *current; current = filemap; while (current != NULL) { if(current->id == intype) { return current->ptp_id; } current = current->next; } // printf("map_libmtp_type_to_ptp_type: unknown filetype.\n"); return PTP_OFC_Undefined;}/** * Returns the PTP internal filetype that maps to a certain libmtp * interface file type. * @param intype the PTP (libgphoto2) interface type * @return the MTP library interface type */static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype){ filemap_t *current; current = filemap; while (current != NULL) { if(current->ptp_id == intype) { return current->id; } current = current->next; } // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n"); return LIBMTP_FILETYPE_UNKNOWN;}/** * Initialize the library. You are only supposed to call this * one, before using the library for the first time in a program. * Never re-initialize libmtp! * * The only thing this does at the moment is to initialise the * filetype mapping table. */void LIBMTP_Init(void){ init_filemap(); return;}/** * This helper function returns a textual description for a libmtp * file type to be used in dialog boxes etc. * @param intype the libmtp internal filetype to get a description for. * @return a string representing the filetype, this must <b>NOT</b> * be free():ed by the caller! */char const * LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t intype){ filemap_t *current; current = filemap; while (current != NULL) { if(current->id == intype) { return current->description; } current = current->next; } return "Unknown filetype";}/** * Retrieves a string from an object * * @param device a pointer to an MTP device. * @param object_id Object reference * @param attribute_id PTP attribute ID * @return valid string or NULL on failure. The returned string * must bee <code>free()</code>:ed by the caller after * use. */static char *get_string_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id){ PTPPropertyValue propval; char *retstring = NULL; PTPParams *params = (PTPParams *) device->params; uint16_t ret; if ( device == NULL || object_id == 0) { return NULL; } ret = ptp_mtp_getobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_STR); if (ret == PTP_RC_OK) { if (propval.str != NULL) { retstring = (char *) strdup(propval.str); free(propval.str); } } return retstring;}/** * Retrieves an unsigned 32-bit integer from an object attribute * * @param device a pointer to an MTP device. * @param object_id Object reference * @param attribute_id PTP attribute ID * @param value_default Default value to return on failure * @return the value */static uint32_t get_u32_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id, uint16_t const attribute_id, uint32_t const value_default){ PTPPropertyValue propval; uint32_t retval = value_default; PTPParams *params = (PTPParams *) device->params; uint16_t ret; if ( device == NULL ) { return value_default; } ret = ptp_mtp_getobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT32); if (ret == PTP_RC_OK) { retval = propval.u32; } return retval;}/** * Retrieves an unsigned 16-bit integer from an object attribute * * @param device a pointer to an MTP device. * @param object_id Object reference * @param attribute_id PTP attribute ID * @param value_default Default value to return on failure * @return a value */static uint16_t get_u16_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id, uint16_t const attribute_id, uint16_t const value_default){ PTPPropertyValue propval; uint16_t retval = value_default; PTPParams *params = (PTPParams *) device->params; uint16_t ret; if ( device == NULL ) { return value_default; } ret = ptp_mtp_getobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT16); if (ret == PTP_RC_OK) { retval = propval.u16; } return retval;}/** * Retrieves an unsigned 8-bit integer from an object attribute * * @param device a pointer to an MTP device. * @param object_id Object reference
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?