Home | History | Annotate | Download | only in src
      1 /**
      2  * \file libmtp.c
      3  *
      4  * Copyright (C) 2005-2011 Linus Walleij <triad (at) df.lth.se>
      5  * Copyright (C) 2005-2008 Richard A. Low <richard (at) wentnet.com>
      6  * Copyright (C) 2007 Ted Bullock <tbullock (at) canada.com>
      7  * Copyright (C) 2007 Tero Saarni <tero.saarni (at) gmail.com>
      8  * Copyright (C) 2008 Florent Mertens <flomertens (at) gmail.com>
      9  *
     10  * This library is free software; you can redistribute it and/or
     11  * modify it under the terms of the GNU Lesser General Public
     12  * License as published by the Free Software Foundation; either
     13  * version 2 of the License, or (at your option) any later version.
     14  *
     15  * This library is distributed in the hope that it will be useful,
     16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18  * Lesser General Public License for more details.
     19  *
     20  * You should have received a copy of the GNU Lesser General Public
     21  * License along with this library; if not, write to the
     22  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     23  * Boston, MA 02111-1307, USA.
     24  *
     25  * This file provides an interface "glue" to the underlying
     26  * PTP implementation from libgphoto2. It uses some local
     27  * code to convert from/to UTF-8 (stored in unicode.c/.h)
     28  * and some small utility functions, mainly for debugging
     29  * (stored in util.c/.h).
     30  *
     31  * The three PTP files (ptp.c, ptp.h and ptp-pack.c) are
     32  * plain copied from the libhphoto2 codebase.
     33  *
     34  * The files libusb-glue.c/.h are just what they say: an
     35  * interface to libusb for the actual, physical USB traffic.
     36  */
     37 #include "config.h"
     38 #include "libmtp.h"
     39 #include "unicode.h"
     40 #include "ptp.h"
     41 #include "libusb-glue.h"
     42 #include "device-flags.h"
     43 #include "playlist-spl.h"
     44 #include "util.h"
     45 
     46 #include "mtpz.h"
     47 
     48 #include <stdarg.h>
     49 #include <stdlib.h>
     50 #include <limits.h>
     51 #include <unistd.h>
     52 #include <string.h>
     53 #include <sys/types.h>
     54 #include <sys/stat.h>
     55 #include <fcntl.h>
     56 #include <time.h>
     57 #include <errno.h>
     58 #ifdef _MSC_VER // For MSVC++
     59 #define USE_WINDOWS_IO_H
     60 #include <io.h>
     61 #endif
     62 
     63 
     64 /**
     65  * Global debug level
     66  * We use a flag system to enable a part of logs.
     67  *
     68  * The LIBMTP_DEBUG environment variable sets the debug flags for any binary
     69  * that uses libmtp and calls LIBMTP_Init. The value can be given in decimal
     70  * (must not start with "0" or it will be interpreted in octal), or in
     71  * hexadecimal (must start with "0x").
     72  *
     73  * The value "-1" enables all debug flags.
     74  *
     75  * Some of the utilities in examples/ also take a command-line flag "-d" that
     76  * enables LIBMTP_DEBUG_PTP and LIBMTP_DEBUG_DATA (same as setting
     77  * LIBMTP_DEBUG=9).
     78  *
     79  * Flags (combine by adding the hex values):
     80  *  0x00 [0000 0000] : LIBMTP_DEBUG_NONE  : no debug (default)
     81  *  0x01 [0000 0001] : LIBMTP_DEBUG_PTP   : PTP debug
     82  *  0x02 [0000 0010] : LIBMTP_DEBUG_PLST  : Playlist debug
     83  *  0x04 [0000 0100] : LIBMTP_DEBUG_USB   : USB debug
     84  *  0x08 [0000 1000] : LIBMTP_DEBUG_DATA  : USB data debug
     85  *
     86  * (Please keep this list in sync with libmtp.h.)
     87  */
     88 int LIBMTP_debug = LIBMTP_DEBUG_NONE;
     89 
     90 
     91 /*
     92  * This is a mapping between libmtp internal MTP filetypes and
     93  * the libgphoto2/PTP equivalent defines. We need this because
     94  * otherwise the libmtp.h device has to be dependent on ptp.h
     95  * to be installed too, and we don't want that.
     96  */
     97 //typedef struct filemap_struct filemap_t;
     98 typedef struct filemap_struct {
     99   char *description; /**< Text description for the file type */
    100   LIBMTP_filetype_t id; /**< LIBMTP internal type for the file type */
    101   uint16_t ptp_id; /**< PTP ID for the filetype */
    102   struct filemap_struct *next;
    103 } filemap_t;
    104 
    105 /*
    106  * This is a mapping between libmtp internal MTP properties and
    107  * the libgphoto2/PTP equivalent defines. We need this because
    108  * otherwise the libmtp.h device has to be dependent on ptp.h
    109  * to be installed too, and we don't want that.
    110  */
    111 typedef struct propertymap_struct {
    112   char *description; /**< Text description for the property */
    113   LIBMTP_property_t id; /**< LIBMTP internal type for the property */
    114   uint16_t ptp_id; /**< PTP ID for the property */
    115   struct propertymap_struct *next;
    116 } propertymap_t;
    117 
    118 /*
    119  * This is a simple container for holding our callback and user_data
    120  * for parsing onwards to the usb_event_async function.
    121  */
    122 typedef struct event_cb_data_struct {
    123   LIBMTP_event_cb_fn cb;
    124   void *user_data;
    125 } event_cb_data_t;
    126 
    127 // Global variables
    128 // This holds the global filetype mapping table
    129 static filemap_t *g_filemap = NULL;
    130 // This holds the global property mapping table
    131 static propertymap_t *g_propertymap = NULL;
    132 
    133 static int load_cache_on_demand = 0;
    134 /*
    135  * Forward declarations of local (static) functions.
    136  */
    137 static int register_filetype(char const * const description, LIBMTP_filetype_t const id,
    138 			     uint16_t const ptp_id);
    139 static void init_filemap();
    140 static int register_property(char const * const description, LIBMTP_property_t const id,
    141 			     uint16_t const ptp_id);
    142 static void init_propertymap();
    143 static void add_error_to_errorstack(LIBMTP_mtpdevice_t *device,
    144 				    LIBMTP_error_number_t errornumber,
    145 				    char const * const error_text);
    146 static void add_ptp_error_to_errorstack(LIBMTP_mtpdevice_t *device,
    147 					uint16_t ptp_error,
    148 					char const * const error_text);
    149 static void flush_handles(LIBMTP_mtpdevice_t *device);
    150 static void get_handles_recursively(LIBMTP_mtpdevice_t *device,
    151 				    PTPParams *params,
    152 				    uint32_t storageid,
    153 				    uint32_t parent);
    154 static void free_storage_list(LIBMTP_mtpdevice_t *device);
    155 static int sort_storage_by(LIBMTP_mtpdevice_t *device, int const sortby);
    156 static uint32_t get_writeable_storageid(LIBMTP_mtpdevice_t *device,
    157 					uint64_t fitsize);
    158 static int get_storage_freespace(LIBMTP_mtpdevice_t *device,
    159 				 LIBMTP_devicestorage_t *storage,
    160 				 uint64_t *freespace);
    161 static int check_if_file_fits(LIBMTP_mtpdevice_t *device,
    162 			      LIBMTP_devicestorage_t *storage,
    163 			      uint64_t const filesize);
    164 static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype);
    165 static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype);
    166 static uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty);
    167 static LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t intype);
    168 static int get_device_unicode_property(LIBMTP_mtpdevice_t *device,
    169 				       char **unicstring, uint16_t property);
    170 static uint16_t adjust_u16(uint16_t val, PTPObjectPropDesc *opd);
    171 static uint32_t adjust_u32(uint32_t val, PTPObjectPropDesc *opd);
    172 static char *get_iso8601_stamp(void);
    173 static char *get_string_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
    174 				    uint16_t const attribute_id);
    175 static uint64_t get_u64_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
    176                                     uint16_t const attribute_id, uint64_t const value_default);
    177 static uint32_t get_u32_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
    178 				    uint16_t const attribute_id, uint32_t const value_default);
    179 static uint16_t get_u16_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
    180 				    uint16_t const attribute_id, uint16_t const value_default);
    181 static uint8_t get_u8_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
    182 				  uint16_t const attribute_id, uint8_t const value_default);
    183 static int set_object_string(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
    184 			     uint16_t const attribute_id, char const * const string);
    185 static int set_object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
    186 			  uint16_t const attribute_id, uint32_t const value);
    187 static int set_object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
    188 			  uint16_t const attribute_id, uint16_t const value);
    189 static int set_object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
    190 			 uint16_t const attribute_id, uint8_t const value);
    191 static void get_track_metadata(LIBMTP_mtpdevice_t *device, uint16_t objectformat,
    192 			       LIBMTP_track_t *track);
    193 static LIBMTP_folder_t *get_subfolders_for_folder(LIBMTP_folder_t *list, uint32_t parent);
    194 static int create_new_abstract_list(LIBMTP_mtpdevice_t *device,
    195 				    char const * const name,
    196 				    char const * const artist,
    197 				    char const * const composer,
    198 				    char const * const genre,
    199 				    uint32_t const parenthandle,
    200 				    uint32_t const storageid,
    201 				    uint16_t const objectformat,
    202 				    char const * const suffix,
    203 				    uint32_t * const newid,
    204 				    uint32_t const * const tracks,
    205 				    uint32_t const no_tracks);
    206 static int update_abstract_list(LIBMTP_mtpdevice_t *device,
    207 				char const * const name,
    208 				char const * const artist,
    209 				char const * const composer,
    210 				char const * const genre,
    211 				uint32_t const objecthandle,
    212 				uint16_t const objectformat,
    213 				uint32_t const * const tracks,
    214 				uint32_t const no_tracks);
    215 static int send_file_object_info(LIBMTP_mtpdevice_t *device, LIBMTP_file_t *filedata);
    216 static void add_object_to_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id);
    217 static void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id);
    218 static int set_object_filename(LIBMTP_mtpdevice_t *device,
    219 		uint32_t object_id,
    220 		uint16_t ptp_type,
    221                 const char **newname);
    222 static char *generate_unique_filename(PTPParams* params, char const * const filename);
    223 static int check_filename_exists(PTPParams* params, char const * const filename);
    224 static void LIBMTP_Handle_Event(PTPContainer *ptp_event,
    225                                 LIBMTP_event_t *event, uint32_t *out1);
    226 
    227 /**
    228  * These are to wrap the get/put handlers to convert from the MTP types to PTP types
    229  * in a reliable way
    230  */
    231 typedef struct _MTPDataHandler {
    232 	MTPDataGetFunc		getfunc;
    233 	MTPDataPutFunc		putfunc;
    234 	void			*priv;
    235 } MTPDataHandler;
    236 
    237 static uint16_t get_func_wrapper(PTPParams* params, void* priv, unsigned long wantlen, unsigned char *data, unsigned long *gotlen);
    238 static uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long sendlen, unsigned char *data);
    239 
    240 /**
    241  * Checks if a filename ends with ".ogg". Used in various
    242  * situations when the device has no idea that it support
    243  * OGG but still does.
    244  *
    245  * @param name string to be checked.
    246  * @return 0 if this does not end with ogg, any other
    247  *           value means it does.
    248  */
    249 static int has_ogg_extension(char *name) {
    250   char *ptype;
    251 
    252   if (name == NULL)
    253     return 0;
    254   ptype = strrchr(name,'.');
    255   if (ptype == NULL)
    256     return 0;
    257   if (!strcasecmp (ptype, ".ogg"))
    258     return 1;
    259   return 0;
    260 }
    261 
    262 /**
    263  * Checks if a filename ends with ".flac". Used in various
    264  * situations when the device has no idea that it support
    265  * FLAC but still does.
    266  *
    267  * @param name string to be checked.
    268  * @return 0 if this does not end with flac, any other
    269  *           value means it does.
    270  */
    271 static int has_flac_extension(char *name) {
    272   char *ptype;
    273 
    274   if (name == NULL)
    275     return 0;
    276   ptype = strrchr(name,'.');
    277   if (ptype == NULL)
    278     return 0;
    279   if (!strcasecmp (ptype, ".flac"))
    280     return 1;
    281   return 0;
    282 }
    283 
    284 
    285 
    286 /**
    287  * Create a new file mapping entry
    288  * @return a newly allocated filemapping entry.
    289  */
    290 static filemap_t *new_filemap_entry()
    291 {
    292   filemap_t *filemap;
    293 
    294   filemap = (filemap_t *)malloc(sizeof(filemap_t));
    295 
    296   if( filemap != NULL ) {
    297     filemap->description = NULL;
    298     filemap->id = LIBMTP_FILETYPE_UNKNOWN;
    299     filemap->ptp_id = PTP_OFC_Undefined;
    300     filemap->next = NULL;
    301   }
    302 
    303   return filemap;
    304 }
    305 
    306 /**
    307  * Register an MTP or PTP filetype for data retrieval
    308  *
    309  * @param description Text description of filetype
    310  * @param id libmtp internal filetype id
    311  * @param ptp_id PTP filetype id
    312  * @return 0 for success any other value means error.
    313 */
    314 static int register_filetype(char const * const description, LIBMTP_filetype_t const id,
    315 			     uint16_t const ptp_id)
    316 {
    317   filemap_t *new = NULL, *current;
    318 
    319   // Has this LIBMTP filetype been registered before ?
    320   current = g_filemap;
    321   while (current != NULL) {
    322     if(current->id == id) {
    323       break;
    324     }
    325     current = current->next;
    326   }
    327 
    328   // Create the entry
    329   if(current == NULL) {
    330     new = new_filemap_entry();
    331     if(new == NULL) {
    332       return 1;
    333     }
    334 
    335     new->id = id;
    336     if(description != NULL) {
    337       new->description = strdup(description);
    338     }
    339     new->ptp_id = ptp_id;
    340 
    341     // Add the entry to the list
    342     if(g_filemap == NULL) {
    343       g_filemap = new;
    344     } else {
    345       current = g_filemap;
    346       while (current->next != NULL ) current=current->next;
    347       current->next = new;
    348     }
    349     // Update the existing entry
    350   } else {
    351     if (current->description != NULL) {
    352       free(current->description);
    353     }
    354     current->description = NULL;
    355     if(description != NULL) {
    356       current->description = strdup(description);
    357     }
    358     current->ptp_id = ptp_id;
    359   }
    360 
    361   return 0;
    362 }
    363 
    364 static void init_filemap()
    365 {
    366   register_filetype("Folder", LIBMTP_FILETYPE_FOLDER, PTP_OFC_Association);
    367   register_filetype("MediaCard", LIBMTP_FILETYPE_MEDIACARD, PTP_OFC_MTP_MediaCard);
    368   register_filetype("RIFF WAVE file", LIBMTP_FILETYPE_WAV, PTP_OFC_WAV);
    369   register_filetype("ISO MPEG-1 Audio Layer 3", LIBMTP_FILETYPE_MP3, PTP_OFC_MP3);
    370   register_filetype("ISO MPEG-1 Audio Layer 2", LIBMTP_FILETYPE_MP2, PTP_OFC_MTP_MP2);
    371   register_filetype("Microsoft Windows Media Audio", LIBMTP_FILETYPE_WMA, PTP_OFC_MTP_WMA);
    372   register_filetype("Ogg container format", LIBMTP_FILETYPE_OGG, PTP_OFC_MTP_OGG);
    373   register_filetype("Free Lossless Audio Codec (FLAC)", LIBMTP_FILETYPE_FLAC, PTP_OFC_MTP_FLAC);
    374   register_filetype("Advanced Audio Coding (AAC)/MPEG-2 Part 7/MPEG-4 Part 3", LIBMTP_FILETYPE_AAC, PTP_OFC_MTP_AAC);
    375   register_filetype("MPEG-4 Part 14 Container Format (Audio Emphasis)", LIBMTP_FILETYPE_M4A, PTP_OFC_MTP_M4A);
    376   register_filetype("MPEG-4 Part 14 Container Format (Audio+Video Emphasis)", LIBMTP_FILETYPE_MP4, PTP_OFC_MTP_MP4);
    377   register_filetype("Audible.com Audio Codec", LIBMTP_FILETYPE_AUDIBLE, PTP_OFC_MTP_AudibleCodec);
    378   register_filetype("Undefined audio file", LIBMTP_FILETYPE_UNDEF_AUDIO, PTP_OFC_MTP_UndefinedAudio);
    379   register_filetype("Microsoft Windows Media Video", LIBMTP_FILETYPE_WMV, PTP_OFC_MTP_WMV);
    380   register_filetype("Audio Video Interleave", LIBMTP_FILETYPE_AVI, PTP_OFC_AVI);
    381   register_filetype("MPEG video stream", LIBMTP_FILETYPE_MPEG, PTP_OFC_MPEG);
    382   register_filetype("Microsoft Advanced Systems Format", LIBMTP_FILETYPE_ASF, PTP_OFC_ASF);
    383   register_filetype("Apple Quicktime container format", LIBMTP_FILETYPE_QT, PTP_OFC_QT);
    384   register_filetype("Undefined video file", LIBMTP_FILETYPE_UNDEF_VIDEO, PTP_OFC_MTP_UndefinedVideo);
    385   register_filetype("JPEG file", LIBMTP_FILETYPE_JPEG, PTP_OFC_EXIF_JPEG);
    386   register_filetype("JP2 file", LIBMTP_FILETYPE_JP2, PTP_OFC_JP2);
    387   register_filetype("JPX file", LIBMTP_FILETYPE_JPX, PTP_OFC_JPX);
    388   register_filetype("JFIF file", LIBMTP_FILETYPE_JFIF, PTP_OFC_JFIF);
    389   register_filetype("TIFF bitmap file", LIBMTP_FILETYPE_TIFF, PTP_OFC_TIFF);
    390   register_filetype("BMP bitmap file", LIBMTP_FILETYPE_BMP, PTP_OFC_BMP);
    391   register_filetype("GIF bitmap file", LIBMTP_FILETYPE_GIF, PTP_OFC_GIF);
    392   register_filetype("PICT bitmap file", LIBMTP_FILETYPE_PICT, PTP_OFC_PICT);
    393   register_filetype("Portable Network Graphics", LIBMTP_FILETYPE_PNG, PTP_OFC_PNG);
    394   register_filetype("Microsoft Windows Image Format", LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT, PTP_OFC_MTP_WindowsImageFormat);
    395   register_filetype("VCalendar version 1", LIBMTP_FILETYPE_VCALENDAR1, PTP_OFC_MTP_vCalendar1);
    396   register_filetype("VCalendar version 2", LIBMTP_FILETYPE_VCALENDAR2, PTP_OFC_MTP_vCalendar2);
    397   register_filetype("VCard version 2", LIBMTP_FILETYPE_VCARD2, PTP_OFC_MTP_vCard2);
    398   register_filetype("VCard version 3", LIBMTP_FILETYPE_VCARD3, PTP_OFC_MTP_vCard3);
    399   register_filetype("Undefined Windows executable file", LIBMTP_FILETYPE_WINEXEC, PTP_OFC_MTP_UndefinedWindowsExecutable);
    400   register_filetype("Text file", LIBMTP_FILETYPE_TEXT, PTP_OFC_Text);
    401   register_filetype("HTML file", LIBMTP_FILETYPE_HTML, PTP_OFC_HTML);
    402   register_filetype("XML file", LIBMTP_FILETYPE_XML, PTP_OFC_MTP_XMLDocument);
    403   register_filetype("DOC file", LIBMTP_FILETYPE_DOC, PTP_OFC_MTP_MSWordDocument);
    404   register_filetype("XLS file", LIBMTP_FILETYPE_XLS, PTP_OFC_MTP_MSExcelSpreadsheetXLS);
    405   register_filetype("PPT file", LIBMTP_FILETYPE_PPT, PTP_OFC_MTP_MSPowerpointPresentationPPT);
    406   register_filetype("MHT file", LIBMTP_FILETYPE_MHT, PTP_OFC_MTP_MHTCompiledHTMLDocument);
    407   register_filetype("Firmware file", LIBMTP_FILETYPE_FIRMWARE, PTP_OFC_MTP_Firmware);
    408   register_filetype("Abstract Album file", LIBMTP_FILETYPE_ALBUM, PTP_OFC_MTP_AbstractAudioAlbum);
    409   register_filetype("Abstract Playlist file", LIBMTP_FILETYPE_PLAYLIST, PTP_OFC_MTP_AbstractAudioVideoPlaylist);
    410   register_filetype("Undefined filetype", LIBMTP_FILETYPE_UNKNOWN, PTP_OFC_Undefined);
    411 }
    412 
    413 /**
    414  * Returns the PTP filetype that maps to a certain libmtp internal file type.
    415  * @param intype the MTP library interface type
    416  * @return the PTP (libgphoto2) interface type
    417  */
    418 static uint16_t map_libmtp_type_to_ptp_type(LIBMTP_filetype_t intype)
    419 {
    420   filemap_t *current;
    421 
    422   current = g_filemap;
    423 
    424   while (current != NULL) {
    425     if(current->id == intype) {
    426       return current->ptp_id;
    427     }
    428     current = current->next;
    429   }
    430   // printf("map_libmtp_type_to_ptp_type: unknown filetype.\n");
    431   return PTP_OFC_Undefined;
    432 }
    433 
    434 
    435 /**
    436  * Returns the MTP internal interface type that maps to a certain ptp
    437  * interface type.
    438  * @param intype the PTP (libgphoto2) interface type
    439  * @return the MTP library interface type
    440  */
    441 static LIBMTP_filetype_t map_ptp_type_to_libmtp_type(uint16_t intype)
    442 {
    443   filemap_t *current;
    444 
    445   current = g_filemap;
    446 
    447   while (current != NULL) {
    448     if(current->ptp_id == intype) {
    449       return current->id;
    450     }
    451     current = current->next;
    452   }
    453   // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n");
    454   return LIBMTP_FILETYPE_UNKNOWN;
    455 }
    456 
    457 /**
    458  * Create a new property mapping entry
    459  * @return a newly allocated propertymapping entry.
    460  */
    461 static propertymap_t *new_propertymap_entry()
    462 {
    463   propertymap_t *propertymap;
    464 
    465   propertymap = (propertymap_t *)malloc(sizeof(propertymap_t));
    466 
    467   if( propertymap != NULL ) {
    468     propertymap->description = NULL;
    469     propertymap->id = LIBMTP_PROPERTY_UNKNOWN;
    470     propertymap->ptp_id = 0;
    471     propertymap->next = NULL;
    472   }
    473 
    474   return propertymap;
    475 }
    476 
    477 /**
    478  * Register an MTP or PTP property for data retrieval
    479  *
    480  * @param description Text description of property
    481  * @param id libmtp internal property id
    482  * @param ptp_id PTP property id
    483  * @return 0 for success any other value means error.
    484 */
    485 static int register_property(char const * const description, LIBMTP_property_t const id,
    486 			     uint16_t const ptp_id)
    487 {
    488   propertymap_t *new = NULL, *current;
    489 
    490   // Has this LIBMTP propety been registered before ?
    491   current = g_propertymap;
    492   while (current != NULL) {
    493     if(current->id == id) {
    494       break;
    495     }
    496     current = current->next;
    497   }
    498 
    499   // Create the entry
    500   if(current == NULL) {
    501     new = new_propertymap_entry();
    502     if(new == NULL) {
    503       return 1;
    504     }
    505 
    506     new->id = id;
    507     if(description != NULL) {
    508       new->description = strdup(description);
    509     }
    510     new->ptp_id = ptp_id;
    511 
    512     // Add the entry to the list
    513     if(g_propertymap == NULL) {
    514       g_propertymap = new;
    515     } else {
    516       current = g_propertymap;
    517       while (current->next != NULL ) current=current->next;
    518       current->next = new;
    519     }
    520     // Update the existing entry
    521   } else {
    522     if (current->description != NULL) {
    523       free(current->description);
    524     }
    525     current->description = NULL;
    526     if(description != NULL) {
    527       current->description = strdup(description);
    528     }
    529     current->ptp_id = ptp_id;
    530   }
    531 
    532   return 0;
    533 }
    534 
    535 static void init_propertymap()
    536 {
    537   register_property("Storage ID", LIBMTP_PROPERTY_StorageID, PTP_OPC_StorageID);
    538   register_property("Object Format", LIBMTP_PROPERTY_ObjectFormat, PTP_OPC_ObjectFormat);
    539   register_property("Protection Status", LIBMTP_PROPERTY_ProtectionStatus, PTP_OPC_ProtectionStatus);
    540   register_property("Object Size", LIBMTP_PROPERTY_ObjectSize, PTP_OPC_ObjectSize);
    541   register_property("Association Type", LIBMTP_PROPERTY_AssociationType, PTP_OPC_AssociationType);
    542   register_property("Association Desc", LIBMTP_PROPERTY_AssociationDesc, PTP_OPC_AssociationDesc);
    543   register_property("Object File Name", LIBMTP_PROPERTY_ObjectFileName, PTP_OPC_ObjectFileName);
    544   register_property("Date Created", LIBMTP_PROPERTY_DateCreated, PTP_OPC_DateCreated);
    545   register_property("Date Modified", LIBMTP_PROPERTY_DateModified, PTP_OPC_DateModified);
    546   register_property("Keywords", LIBMTP_PROPERTY_Keywords, PTP_OPC_Keywords);
    547   register_property("Parent Object", LIBMTP_PROPERTY_ParentObject, PTP_OPC_ParentObject);
    548   register_property("Allowed Folder Contents", LIBMTP_PROPERTY_AllowedFolderContents, PTP_OPC_AllowedFolderContents);
    549   register_property("Hidden", LIBMTP_PROPERTY_Hidden, PTP_OPC_Hidden);
    550   register_property("System Object", LIBMTP_PROPERTY_SystemObject, PTP_OPC_SystemObject);
    551   register_property("Persistant Unique Object Identifier", LIBMTP_PROPERTY_PersistantUniqueObjectIdentifier, PTP_OPC_PersistantUniqueObjectIdentifier);
    552   register_property("Sync ID", LIBMTP_PROPERTY_SyncID, PTP_OPC_SyncID);
    553   register_property("Property Bag", LIBMTP_PROPERTY_PropertyBag, PTP_OPC_PropertyBag);
    554   register_property("Name", LIBMTP_PROPERTY_Name, PTP_OPC_Name);
    555   register_property("Created By", LIBMTP_PROPERTY_CreatedBy, PTP_OPC_CreatedBy);
    556   register_property("Artist", LIBMTP_PROPERTY_Artist, PTP_OPC_Artist);
    557   register_property("Date Authored", LIBMTP_PROPERTY_DateAuthored, PTP_OPC_DateAuthored);
    558   register_property("Description", LIBMTP_PROPERTY_Description, PTP_OPC_Description);
    559   register_property("URL Reference", LIBMTP_PROPERTY_URLReference, PTP_OPC_URLReference);
    560   register_property("Language Locale", LIBMTP_PROPERTY_LanguageLocale, PTP_OPC_LanguageLocale);
    561   register_property("Copyright Information", LIBMTP_PROPERTY_CopyrightInformation, PTP_OPC_CopyrightInformation);
    562   register_property("Source", LIBMTP_PROPERTY_Source, PTP_OPC_Source);
    563   register_property("Origin Location", LIBMTP_PROPERTY_OriginLocation, PTP_OPC_OriginLocation);
    564   register_property("Date Added", LIBMTP_PROPERTY_DateAdded, PTP_OPC_DateAdded);
    565   register_property("Non Consumable", LIBMTP_PROPERTY_NonConsumable, PTP_OPC_NonConsumable);
    566   register_property("Corrupt Or Unplayable", LIBMTP_PROPERTY_CorruptOrUnplayable, PTP_OPC_CorruptOrUnplayable);
    567   register_property("Producer Serial Number", LIBMTP_PROPERTY_ProducerSerialNumber, PTP_OPC_ProducerSerialNumber);
    568   register_property("Representative Sample Format", LIBMTP_PROPERTY_RepresentativeSampleFormat, PTP_OPC_RepresentativeSampleFormat);
    569   register_property("Representative Sample Sise", LIBMTP_PROPERTY_RepresentativeSampleSize, PTP_OPC_RepresentativeSampleSize);
    570   register_property("Representative Sample Height", LIBMTP_PROPERTY_RepresentativeSampleHeight, PTP_OPC_RepresentativeSampleHeight);
    571   register_property("Representative Sample Width", LIBMTP_PROPERTY_RepresentativeSampleWidth, PTP_OPC_RepresentativeSampleWidth);
    572   register_property("Representative Sample Duration", LIBMTP_PROPERTY_RepresentativeSampleDuration, PTP_OPC_RepresentativeSampleDuration);
    573   register_property("Representative Sample Data", LIBMTP_PROPERTY_RepresentativeSampleData, PTP_OPC_RepresentativeSampleData);
    574   register_property("Width", LIBMTP_PROPERTY_Width, PTP_OPC_Width);
    575   register_property("Height", LIBMTP_PROPERTY_Height, PTP_OPC_Height);
    576   register_property("Duration", LIBMTP_PROPERTY_Duration, PTP_OPC_Duration);
    577   register_property("Rating", LIBMTP_PROPERTY_Rating, PTP_OPC_Rating);
    578   register_property("Track", LIBMTP_PROPERTY_Track, PTP_OPC_Track);
    579   register_property("Genre", LIBMTP_PROPERTY_Genre, PTP_OPC_Genre);
    580   register_property("Credits", LIBMTP_PROPERTY_Credits, PTP_OPC_Credits);
    581   register_property("Lyrics", LIBMTP_PROPERTY_Lyrics, PTP_OPC_Lyrics);
    582   register_property("Subscription Content ID", LIBMTP_PROPERTY_SubscriptionContentID, PTP_OPC_SubscriptionContentID);
    583   register_property("Produced By", LIBMTP_PROPERTY_ProducedBy, PTP_OPC_ProducedBy);
    584   register_property("Use Count", LIBMTP_PROPERTY_UseCount, PTP_OPC_UseCount);
    585   register_property("Skip Count", LIBMTP_PROPERTY_SkipCount, PTP_OPC_SkipCount);
    586   register_property("Last Accessed", LIBMTP_PROPERTY_LastAccessed, PTP_OPC_LastAccessed);
    587   register_property("Parental Rating", LIBMTP_PROPERTY_ParentalRating, PTP_OPC_ParentalRating);
    588   register_property("Meta Genre", LIBMTP_PROPERTY_MetaGenre, PTP_OPC_MetaGenre);
    589   register_property("Composer", LIBMTP_PROPERTY_Composer, PTP_OPC_Composer);
    590   register_property("Effective Rating", LIBMTP_PROPERTY_EffectiveRating, PTP_OPC_EffectiveRating);
    591   register_property("Subtitle", LIBMTP_PROPERTY_Subtitle, PTP_OPC_Subtitle);
    592   register_property("Original Release Date", LIBMTP_PROPERTY_OriginalReleaseDate, PTP_OPC_OriginalReleaseDate);
    593   register_property("Album Name", LIBMTP_PROPERTY_AlbumName, PTP_OPC_AlbumName);
    594   register_property("Album Artist", LIBMTP_PROPERTY_AlbumArtist, PTP_OPC_AlbumArtist);
    595   register_property("Mood", LIBMTP_PROPERTY_Mood, PTP_OPC_Mood);
    596   register_property("DRM Status", LIBMTP_PROPERTY_DRMStatus, PTP_OPC_DRMStatus);
    597   register_property("Sub Description", LIBMTP_PROPERTY_SubDescription, PTP_OPC_SubDescription);
    598   register_property("Is Cropped", LIBMTP_PROPERTY_IsCropped, PTP_OPC_IsCropped);
    599   register_property("Is Color Corrected", LIBMTP_PROPERTY_IsColorCorrected, PTP_OPC_IsColorCorrected);
    600   register_property("Image Bit Depth", LIBMTP_PROPERTY_ImageBitDepth, PTP_OPC_ImageBitDepth);
    601   register_property("f Number", LIBMTP_PROPERTY_Fnumber, PTP_OPC_Fnumber);
    602   register_property("Exposure Time", LIBMTP_PROPERTY_ExposureTime, PTP_OPC_ExposureTime);
    603   register_property("Exposure Index", LIBMTP_PROPERTY_ExposureIndex, PTP_OPC_ExposureIndex);
    604   register_property("Display Name", LIBMTP_PROPERTY_DisplayName, PTP_OPC_DisplayName);
    605   register_property("Body Text", LIBMTP_PROPERTY_BodyText, PTP_OPC_BodyText);
    606   register_property("Subject", LIBMTP_PROPERTY_Subject, PTP_OPC_Subject);
    607   register_property("Priority", LIBMTP_PROPERTY_Priority, PTP_OPC_Priority);
    608   register_property("Given Name", LIBMTP_PROPERTY_GivenName, PTP_OPC_GivenName);
    609   register_property("Middle Names", LIBMTP_PROPERTY_MiddleNames, PTP_OPC_MiddleNames);
    610   register_property("Family Name", LIBMTP_PROPERTY_FamilyName, PTP_OPC_FamilyName);
    611   register_property("Prefix", LIBMTP_PROPERTY_Prefix, PTP_OPC_Prefix);
    612   register_property("Suffix", LIBMTP_PROPERTY_Suffix, PTP_OPC_Suffix);
    613   register_property("Phonetic Given Name", LIBMTP_PROPERTY_PhoneticGivenName, PTP_OPC_PhoneticGivenName);
    614   register_property("Phonetic Family Name", LIBMTP_PROPERTY_PhoneticFamilyName, PTP_OPC_PhoneticFamilyName);
    615   register_property("Email: Primary", LIBMTP_PROPERTY_EmailPrimary, PTP_OPC_EmailPrimary);
    616   register_property("Email: Personal 1", LIBMTP_PROPERTY_EmailPersonal1, PTP_OPC_EmailPersonal1);
    617   register_property("Email: Personal 2", LIBMTP_PROPERTY_EmailPersonal2, PTP_OPC_EmailPersonal2);
    618   register_property("Email: Business 1", LIBMTP_PROPERTY_EmailBusiness1, PTP_OPC_EmailBusiness1);
    619   register_property("Email: Business 2", LIBMTP_PROPERTY_EmailBusiness2, PTP_OPC_EmailBusiness2);
    620   register_property("Email: Others", LIBMTP_PROPERTY_EmailOthers, PTP_OPC_EmailOthers);
    621   register_property("Phone Number: Primary", LIBMTP_PROPERTY_PhoneNumberPrimary, PTP_OPC_PhoneNumberPrimary);
    622   register_property("Phone Number: Personal", LIBMTP_PROPERTY_PhoneNumberPersonal, PTP_OPC_PhoneNumberPersonal);
    623   register_property("Phone Number: Personal 2", LIBMTP_PROPERTY_PhoneNumberPersonal2, PTP_OPC_PhoneNumberPersonal2);
    624   register_property("Phone Number: Business", LIBMTP_PROPERTY_PhoneNumberBusiness, PTP_OPC_PhoneNumberBusiness);
    625   register_property("Phone Number: Business 2", LIBMTP_PROPERTY_PhoneNumberBusiness2, PTP_OPC_PhoneNumberBusiness2);
    626   register_property("Phone Number: Mobile", LIBMTP_PROPERTY_PhoneNumberMobile, PTP_OPC_PhoneNumberMobile);
    627   register_property("Phone Number: Mobile 2", LIBMTP_PROPERTY_PhoneNumberMobile2, PTP_OPC_PhoneNumberMobile2);
    628   register_property("Fax Number: Primary", LIBMTP_PROPERTY_FaxNumberPrimary, PTP_OPC_FaxNumberPrimary);
    629   register_property("Fax Number: Personal", LIBMTP_PROPERTY_FaxNumberPersonal, PTP_OPC_FaxNumberPersonal);
    630   register_property("Fax Number: Business", LIBMTP_PROPERTY_FaxNumberBusiness, PTP_OPC_FaxNumberBusiness);
    631   register_property("Pager Number", LIBMTP_PROPERTY_PagerNumber, PTP_OPC_PagerNumber);
    632   register_property("Phone Number: Others", LIBMTP_PROPERTY_PhoneNumberOthers, PTP_OPC_PhoneNumberOthers);
    633   register_property("Primary Web Address", LIBMTP_PROPERTY_PrimaryWebAddress, PTP_OPC_PrimaryWebAddress);
    634   register_property("Personal Web Address", LIBMTP_PROPERTY_PersonalWebAddress, PTP_OPC_PersonalWebAddress);
    635   register_property("Business Web Address", LIBMTP_PROPERTY_BusinessWebAddress, PTP_OPC_BusinessWebAddress);
    636   register_property("Instant Messenger Address 1", LIBMTP_PROPERTY_InstantMessengerAddress, PTP_OPC_InstantMessengerAddress);
    637   register_property("Instant Messenger Address 2", LIBMTP_PROPERTY_InstantMessengerAddress2, PTP_OPC_InstantMessengerAddress2);
    638   register_property("Instant Messenger Address 3", LIBMTP_PROPERTY_InstantMessengerAddress3, PTP_OPC_InstantMessengerAddress3);
    639   register_property("Postal Address: Personal: Full", LIBMTP_PROPERTY_PostalAddressPersonalFull, PTP_OPC_PostalAddressPersonalFull);
    640   register_property("Postal Address: Personal: Line 1", LIBMTP_PROPERTY_PostalAddressPersonalFullLine1, PTP_OPC_PostalAddressPersonalFullLine1);
    641   register_property("Postal Address: Personal: Line 2", LIBMTP_PROPERTY_PostalAddressPersonalFullLine2, PTP_OPC_PostalAddressPersonalFullLine2);
    642   register_property("Postal Address: Personal: City", LIBMTP_PROPERTY_PostalAddressPersonalFullCity, PTP_OPC_PostalAddressPersonalFullCity);
    643   register_property("Postal Address: Personal: Region", LIBMTP_PROPERTY_PostalAddressPersonalFullRegion, PTP_OPC_PostalAddressPersonalFullRegion);
    644   register_property("Postal Address: Personal: Postal Code", LIBMTP_PROPERTY_PostalAddressPersonalFullPostalCode, PTP_OPC_PostalAddressPersonalFullPostalCode);
    645   register_property("Postal Address: Personal: Country", LIBMTP_PROPERTY_PostalAddressPersonalFullCountry, PTP_OPC_PostalAddressPersonalFullCountry);
    646   register_property("Postal Address: Business: Full", LIBMTP_PROPERTY_PostalAddressBusinessFull, PTP_OPC_PostalAddressBusinessFull);
    647   register_property("Postal Address: Business: Line 1", LIBMTP_PROPERTY_PostalAddressBusinessLine1, PTP_OPC_PostalAddressBusinessLine1);
    648   register_property("Postal Address: Business: Line 2", LIBMTP_PROPERTY_PostalAddressBusinessLine2, PTP_OPC_PostalAddressBusinessLine2);
    649   register_property("Postal Address: Business: City", LIBMTP_PROPERTY_PostalAddressBusinessCity, PTP_OPC_PostalAddressBusinessCity);
    650   register_property("Postal Address: Business: Region", LIBMTP_PROPERTY_PostalAddressBusinessRegion, PTP_OPC_PostalAddressBusinessRegion);
    651   register_property("Postal Address: Business: Postal Code", LIBMTP_PROPERTY_PostalAddressBusinessPostalCode, PTP_OPC_PostalAddressBusinessPostalCode);
    652   register_property("Postal Address: Business: Country", LIBMTP_PROPERTY_PostalAddressBusinessCountry, PTP_OPC_PostalAddressBusinessCountry);
    653   register_property("Postal Address: Other: Full", LIBMTP_PROPERTY_PostalAddressOtherFull, PTP_OPC_PostalAddressOtherFull);
    654   register_property("Postal Address: Other: Line 1", LIBMTP_PROPERTY_PostalAddressOtherLine1, PTP_OPC_PostalAddressOtherLine1);
    655   register_property("Postal Address: Other: Line 2", LIBMTP_PROPERTY_PostalAddressOtherLine2, PTP_OPC_PostalAddressOtherLine2);
    656   register_property("Postal Address: Other: City", LIBMTP_PROPERTY_PostalAddressOtherCity, PTP_OPC_PostalAddressOtherCity);
    657   register_property("Postal Address: Other: Region", LIBMTP_PROPERTY_PostalAddressOtherRegion, PTP_OPC_PostalAddressOtherRegion);
    658   register_property("Postal Address: Other: Postal Code", LIBMTP_PROPERTY_PostalAddressOtherPostalCode, PTP_OPC_PostalAddressOtherPostalCode);
    659   register_property("Postal Address: Other: Counrtry", LIBMTP_PROPERTY_PostalAddressOtherCountry, PTP_OPC_PostalAddressOtherCountry);
    660   register_property("Organization Name", LIBMTP_PROPERTY_OrganizationName, PTP_OPC_OrganizationName);
    661   register_property("Phonetic Organization Name", LIBMTP_PROPERTY_PhoneticOrganizationName, PTP_OPC_PhoneticOrganizationName);
    662   register_property("Role", LIBMTP_PROPERTY_Role, PTP_OPC_Role);
    663   register_property("Birthdate", LIBMTP_PROPERTY_Birthdate, PTP_OPC_Birthdate);
    664   register_property("Message To", LIBMTP_PROPERTY_MessageTo, PTP_OPC_MessageTo);
    665   register_property("Message CC", LIBMTP_PROPERTY_MessageCC, PTP_OPC_MessageCC);
    666   register_property("Message BCC", LIBMTP_PROPERTY_MessageBCC, PTP_OPC_MessageBCC);
    667   register_property("Message Read", LIBMTP_PROPERTY_MessageRead, PTP_OPC_MessageRead);
    668   register_property("Message Received Time", LIBMTP_PROPERTY_MessageReceivedTime, PTP_OPC_MessageReceivedTime);
    669   register_property("Message Sender", LIBMTP_PROPERTY_MessageSender, PTP_OPC_MessageSender);
    670   register_property("Activity Begin Time", LIBMTP_PROPERTY_ActivityBeginTime, PTP_OPC_ActivityBeginTime);
    671   register_property("Activity End Time", LIBMTP_PROPERTY_ActivityEndTime, PTP_OPC_ActivityEndTime);
    672   register_property("Activity Location", LIBMTP_PROPERTY_ActivityLocation, PTP_OPC_ActivityLocation);
    673   register_property("Activity Required Attendees", LIBMTP_PROPERTY_ActivityRequiredAttendees, PTP_OPC_ActivityRequiredAttendees);
    674   register_property("Optional Attendees", LIBMTP_PROPERTY_ActivityOptionalAttendees, PTP_OPC_ActivityOptionalAttendees);
    675   register_property("Activity Resources", LIBMTP_PROPERTY_ActivityResources, PTP_OPC_ActivityResources);
    676   register_property("Activity Accepted", LIBMTP_PROPERTY_ActivityAccepted, PTP_OPC_ActivityAccepted);
    677   register_property("Owner", LIBMTP_PROPERTY_Owner, PTP_OPC_Owner);
    678   register_property("Editor", LIBMTP_PROPERTY_Editor, PTP_OPC_Editor);
    679   register_property("Webmaster", LIBMTP_PROPERTY_Webmaster, PTP_OPC_Webmaster);
    680   register_property("URL Source", LIBMTP_PROPERTY_URLSource, PTP_OPC_URLSource);
    681   register_property("URL Destination", LIBMTP_PROPERTY_URLDestination, PTP_OPC_URLDestination);
    682   register_property("Time Bookmark", LIBMTP_PROPERTY_TimeBookmark, PTP_OPC_TimeBookmark);
    683   register_property("Object Bookmark", LIBMTP_PROPERTY_ObjectBookmark, PTP_OPC_ObjectBookmark);
    684   register_property("Byte Bookmark", LIBMTP_PROPERTY_ByteBookmark, PTP_OPC_ByteBookmark);
    685   register_property("Last Build Date", LIBMTP_PROPERTY_LastBuildDate, PTP_OPC_LastBuildDate);
    686   register_property("Time To Live", LIBMTP_PROPERTY_TimetoLive, PTP_OPC_TimetoLive);
    687   register_property("Media GUID", LIBMTP_PROPERTY_MediaGUID, PTP_OPC_MediaGUID);
    688   register_property("Total Bit Rate", LIBMTP_PROPERTY_TotalBitRate, PTP_OPC_TotalBitRate);
    689   register_property("Bit Rate Type", LIBMTP_PROPERTY_BitRateType, PTP_OPC_BitRateType);
    690   register_property("Sample Rate", LIBMTP_PROPERTY_SampleRate, PTP_OPC_SampleRate);
    691   register_property("Number Of Channels", LIBMTP_PROPERTY_NumberOfChannels, PTP_OPC_NumberOfChannels);
    692   register_property("Audio Bit Depth", LIBMTP_PROPERTY_AudioBitDepth, PTP_OPC_AudioBitDepth);
    693   register_property("Scan Depth", LIBMTP_PROPERTY_ScanDepth, PTP_OPC_ScanDepth);
    694   register_property("Audio WAVE Codec", LIBMTP_PROPERTY_AudioWAVECodec, PTP_OPC_AudioWAVECodec);
    695   register_property("Audio Bit Rate", LIBMTP_PROPERTY_AudioBitRate, PTP_OPC_AudioBitRate);
    696   register_property("Video Four CC Codec", LIBMTP_PROPERTY_VideoFourCCCodec, PTP_OPC_VideoFourCCCodec);
    697   register_property("Video Bit Rate", LIBMTP_PROPERTY_VideoBitRate, PTP_OPC_VideoBitRate);
    698   register_property("Frames Per Thousand Seconds", LIBMTP_PROPERTY_FramesPerThousandSeconds, PTP_OPC_FramesPerThousandSeconds);
    699   register_property("Key Frame Distance", LIBMTP_PROPERTY_KeyFrameDistance, PTP_OPC_KeyFrameDistance);
    700   register_property("Buffer Size", LIBMTP_PROPERTY_BufferSize, PTP_OPC_BufferSize);
    701   register_property("Encoding Quality", LIBMTP_PROPERTY_EncodingQuality, PTP_OPC_EncodingQuality);
    702   register_property("Encoding Profile", LIBMTP_PROPERTY_EncodingProfile, PTP_OPC_EncodingProfile);
    703   register_property("Buy flag", LIBMTP_PROPERTY_BuyFlag, PTP_OPC_BuyFlag);
    704   register_property("Unknown property", LIBMTP_PROPERTY_UNKNOWN, 0);
    705 }
    706 
    707 /**
    708  * Returns the PTP property that maps to a certain libmtp internal property type.
    709  * @param inproperty the MTP library interface property
    710  * @return the PTP (libgphoto2) property type
    711  */
    712 static uint16_t map_libmtp_property_to_ptp_property(LIBMTP_property_t inproperty)
    713 {
    714   propertymap_t *current;
    715 
    716   current = g_propertymap;
    717 
    718   while (current != NULL) {
    719     if(current->id == inproperty) {
    720       return current->ptp_id;
    721     }
    722     current = current->next;
    723   }
    724   return 0;
    725 }
    726 
    727 
    728 /**
    729  * Returns the MTP internal interface property that maps to a certain ptp
    730  * interface property.
    731  * @param inproperty the PTP (libgphoto2) interface property
    732  * @return the MTP library interface property
    733  */
    734 static LIBMTP_property_t map_ptp_property_to_libmtp_property(uint16_t inproperty)
    735 {
    736   propertymap_t *current;
    737 
    738   current = g_propertymap;
    739 
    740   while (current != NULL) {
    741     if(current->ptp_id == inproperty) {
    742       return current->id;
    743     }
    744     current = current->next;
    745   }
    746   // printf("map_ptp_type_to_libmtp_type: unknown filetype.\n");
    747   return LIBMTP_PROPERTY_UNKNOWN;
    748 }
    749 
    750 
    751 /**
    752  * Set the debug level.
    753  *
    754  * By default, the debug level is set to '0' (disable).
    755  */
    756 void LIBMTP_Set_Debug(int level)
    757 {
    758   if (LIBMTP_debug || level)
    759     LIBMTP_ERROR("LIBMTP_Set_Debug: Setting debugging level to %d (0x%02x) "
    760                  "(%s)\n", level, level, level ? "on" : "off");
    761 
    762   LIBMTP_debug = level;
    763 }
    764 
    765 
    766 /**
    767  * Initialize the library. You are only supposed to call this
    768  * one, before using the library for the first time in a program.
    769  * Never re-initialize libmtp!
    770  *
    771  * The only thing this does at the moment is to initialise the
    772  * filetype mapping table, as well as load MTPZ data if necessary.
    773  */
    774 void LIBMTP_Init(void)
    775 {
    776   const char *env_debug = getenv("LIBMTP_DEBUG");
    777   if (env_debug) {
    778     const long debug_flags = strtol(env_debug, NULL, 0);
    779     if (debug_flags != LONG_MIN && debug_flags != LONG_MAX &&
    780         INT_MIN <= debug_flags && debug_flags <= INT_MAX) {
    781       LIBMTP_Set_Debug(debug_flags);
    782     } else {
    783       fprintf(stderr, "LIBMTP_Init: error setting debug flags from environment "
    784                       "value \"%s\"\n", env_debug);
    785     }
    786   }
    787 
    788   init_filemap();
    789   init_propertymap();
    790 
    791   if (mtpz_loaddata() == -1)
    792     use_mtpz = 0;
    793   else
    794     use_mtpz = 1;
    795 
    796   return;
    797 }
    798 
    799 
    800 /**
    801  * This helper function returns a textual description for a libmtp
    802  * file type to be used in dialog boxes etc.
    803  * @param intype the libmtp internal filetype to get a description for.
    804  * @return a string representing the filetype, this must <b>NOT</b>
    805  *         be free():ed by the caller!
    806  */
    807 char const * LIBMTP_Get_Filetype_Description(LIBMTP_filetype_t intype)
    808 {
    809   filemap_t *current;
    810 
    811   current = g_filemap;
    812 
    813   while (current != NULL) {
    814     if(current->id == intype) {
    815       return current->description;
    816     }
    817     current = current->next;
    818   }
    819 
    820   return "Unknown filetype";
    821 }
    822 
    823 /**
    824  * This helper function returns a textual description for a libmtp
    825  * property to be used in dialog boxes etc.
    826  * @param inproperty the libmtp internal property to get a description for.
    827  * @return a string representing the filetype, this must <b>NOT</b>
    828  *         be free():ed by the caller!
    829  */
    830 char const * LIBMTP_Get_Property_Description(LIBMTP_property_t inproperty)
    831 {
    832   propertymap_t *current;
    833 
    834   current = g_propertymap;
    835 
    836   while (current != NULL) {
    837     if(current->id == inproperty) {
    838       return current->description;
    839     }
    840     current = current->next;
    841   }
    842 
    843   return "Unknown property";
    844 }
    845 
    846 /**
    847  * This function will do its best to fit a 16bit
    848  * value into a PTP object property if the property
    849  * is limited in range or step sizes.
    850  */
    851 static uint16_t adjust_u16(uint16_t val, PTPObjectPropDesc *opd)
    852 {
    853   switch (opd->FormFlag) {
    854   case PTP_DPFF_Range:
    855     if (val < opd->FORM.Range.MinimumValue.u16) {
    856       return opd->FORM.Range.MinimumValue.u16;
    857     }
    858     if (val > opd->FORM.Range.MaximumValue.u16) {
    859       return opd->FORM.Range.MaximumValue.u16;
    860     }
    861     // Round down to last step.
    862     if (val % opd->FORM.Range.StepSize.u16 != 0) {
    863       return val - (val % opd->FORM.Range.StepSize.u16);
    864     }
    865     return val;
    866     break;
    867   case PTP_DPFF_Enumeration:
    868     {
    869       int i;
    870       uint16_t bestfit = opd->FORM.Enum.SupportedValue[0].u16;
    871 
    872       for (i=0; i<opd->FORM.Enum.NumberOfValues; i++) {
    873 	if (val == opd->FORM.Enum.SupportedValue[i].u16) {
    874 	  return val;
    875 	}
    876 	// Rough guess of best fit
    877 	if (opd->FORM.Enum.SupportedValue[i].u16 < val) {
    878 	  bestfit = opd->FORM.Enum.SupportedValue[i].u16;
    879 	}
    880       }
    881       // Just some default that'll work.
    882       return bestfit;
    883     }
    884   default:
    885     // Will accept any value
    886     break;
    887   }
    888   return val;
    889 }
    890 
    891 /**
    892  * This function will do its best to fit a 32bit
    893  * value into a PTP object property if the property
    894  * is limited in range or step sizes.
    895  */
    896 static uint32_t adjust_u32(uint32_t val, PTPObjectPropDesc *opd)
    897 {
    898   switch (opd->FormFlag) {
    899   case PTP_DPFF_Range:
    900     if (val < opd->FORM.Range.MinimumValue.u32) {
    901       return opd->FORM.Range.MinimumValue.u32;
    902     }
    903     if (val > opd->FORM.Range.MaximumValue.u32) {
    904       return opd->FORM.Range.MaximumValue.u32;
    905     }
    906     // Round down to last step.
    907     if (val % opd->FORM.Range.StepSize.u32 != 0) {
    908       return val - (val % opd->FORM.Range.StepSize.u32);
    909     }
    910     return val;
    911     break;
    912   case PTP_DPFF_Enumeration:
    913     {
    914       int i;
    915       uint32_t bestfit = opd->FORM.Enum.SupportedValue[0].u32;
    916 
    917       for (i=0; i<opd->FORM.Enum.NumberOfValues; i++) {
    918 	if (val == opd->FORM.Enum.SupportedValue[i].u32) {
    919 	  return val;
    920 	}
    921 	// Rough guess of best fit
    922 	if (opd->FORM.Enum.SupportedValue[i].u32 < val) {
    923 	  bestfit = opd->FORM.Enum.SupportedValue[i].u32;
    924 	}
    925       }
    926       // Just some default that'll work.
    927       return bestfit;
    928     }
    929   default:
    930     // Will accept any value
    931     break;
    932   }
    933   return val;
    934 }
    935 
    936 /**
    937  * This function returns a newly created ISO 8601 timestamp with the
    938  * current time in as high precision as possible. It even adds
    939  * the time zone if it can.
    940  */
    941 static char *get_iso8601_stamp(void)
    942 {
    943   time_t curtime;
    944   struct tm *loctime;
    945   char tmp[64];
    946 
    947   curtime = time(NULL);
    948   loctime = localtime(&curtime);
    949   strftime (tmp, sizeof(tmp), "%Y%m%dT%H%M%S.0%z", loctime);
    950   return strdup(tmp);
    951 }
    952 
    953 /**
    954  * Gets the allowed values (range or enum) for a property
    955  * @param device a pointer to an MTP device
    956  * @param property the property to query
    957  * @param filetype the filetype of the object you want to set values for
    958  * @param allowed_vals pointer to a LIBMTP_allowed_values_t struct to
    959  *        receive the allowed values.  Call LIBMTP_destroy_allowed_values_t
    960  *        on this on successful completion.
    961  * @return 0 on success, any other value means failure
    962  */
    963 int LIBMTP_Get_Allowed_Property_Values(LIBMTP_mtpdevice_t *device, LIBMTP_property_t const property,
    964             LIBMTP_filetype_t const filetype, LIBMTP_allowed_values_t *allowed_vals)
    965 {
    966   PTPObjectPropDesc opd;
    967   uint16_t ret = 0;
    968 
    969   ret = ptp_mtp_getobjectpropdesc(device->params, map_libmtp_property_to_ptp_property(property), map_libmtp_type_to_ptp_type(filetype), &opd);
    970   if (ret != PTP_RC_OK) {
    971     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Allowed_Property_Values(): could not get property description.");
    972     return -1;
    973   }
    974 
    975   if (opd.FormFlag == PTP_OPFF_Enumeration) {
    976     int i = 0;
    977 
    978     allowed_vals->is_range = 0;
    979     allowed_vals->num_entries = opd.FORM.Enum.NumberOfValues;
    980 
    981     switch (opd.DataType)
    982     {
    983       case PTP_DTC_INT8:
    984         allowed_vals->i8vals = malloc(sizeof(int8_t) * opd.FORM.Enum.NumberOfValues);
    985         allowed_vals->datatype = LIBMTP_DATATYPE_INT8;
    986         break;
    987       case PTP_DTC_UINT8:
    988         allowed_vals->u8vals = malloc(sizeof(uint8_t) * opd.FORM.Enum.NumberOfValues);
    989         allowed_vals->datatype = LIBMTP_DATATYPE_UINT8;
    990         break;
    991       case PTP_DTC_INT16:
    992         allowed_vals->i16vals = malloc(sizeof(int16_t) * opd.FORM.Enum.NumberOfValues);
    993         allowed_vals->datatype = LIBMTP_DATATYPE_INT16;
    994         break;
    995       case PTP_DTC_UINT16:
    996         allowed_vals->u16vals = malloc(sizeof(uint16_t) * opd.FORM.Enum.NumberOfValues);
    997         allowed_vals->datatype = LIBMTP_DATATYPE_UINT16;
    998         break;
    999       case PTP_DTC_INT32:
   1000         allowed_vals->i32vals = malloc(sizeof(int32_t) * opd.FORM.Enum.NumberOfValues);
   1001         allowed_vals->datatype = LIBMTP_DATATYPE_INT32;
   1002         break;
   1003       case PTP_DTC_UINT32:
   1004         allowed_vals->u32vals = malloc(sizeof(uint32_t) * opd.FORM.Enum.NumberOfValues);
   1005         allowed_vals->datatype = LIBMTP_DATATYPE_UINT32;
   1006         break;
   1007       case PTP_DTC_INT64:
   1008         allowed_vals->i64vals = malloc(sizeof(int64_t) * opd.FORM.Enum.NumberOfValues);
   1009         allowed_vals->datatype = LIBMTP_DATATYPE_INT64;
   1010         break;
   1011       case PTP_DTC_UINT64:
   1012         allowed_vals->u64vals = malloc(sizeof(uint64_t) * opd.FORM.Enum.NumberOfValues);
   1013         allowed_vals->datatype = LIBMTP_DATATYPE_UINT64;
   1014         break;
   1015     }
   1016 
   1017     for (i = 0; i < opd.FORM.Enum.NumberOfValues; i++) {
   1018       switch (opd.DataType)
   1019       {
   1020         case PTP_DTC_INT8:
   1021           allowed_vals->i8vals[i] = opd.FORM.Enum.SupportedValue[i].i8;
   1022           break;
   1023         case PTP_DTC_UINT8:
   1024           allowed_vals->u8vals[i] = opd.FORM.Enum.SupportedValue[i].u8;
   1025           break;
   1026         case PTP_DTC_INT16:
   1027           allowed_vals->i16vals[i] = opd.FORM.Enum.SupportedValue[i].i16;
   1028           break;
   1029         case PTP_DTC_UINT16:
   1030           allowed_vals->u16vals[i] = opd.FORM.Enum.SupportedValue[i].u16;
   1031           break;
   1032         case PTP_DTC_INT32:
   1033           allowed_vals->i32vals[i] = opd.FORM.Enum.SupportedValue[i].i32;
   1034           break;
   1035         case PTP_DTC_UINT32:
   1036           allowed_vals->u32vals[i] = opd.FORM.Enum.SupportedValue[i].u32;
   1037           break;
   1038         case PTP_DTC_INT64:
   1039           allowed_vals->i64vals[i] = opd.FORM.Enum.SupportedValue[i].i64;
   1040           break;
   1041         case PTP_DTC_UINT64:
   1042           allowed_vals->u64vals[i] = opd.FORM.Enum.SupportedValue[i].u64;
   1043           break;
   1044       }
   1045     }
   1046     ptp_free_objectpropdesc(&opd);
   1047     return 0;
   1048   } else if (opd.FormFlag == PTP_OPFF_Range) {
   1049     allowed_vals->is_range = 1;
   1050 
   1051     switch (opd.DataType)
   1052     {
   1053       case PTP_DTC_INT8:
   1054         allowed_vals->i8min = opd.FORM.Range.MinimumValue.i8;
   1055         allowed_vals->i8max = opd.FORM.Range.MaximumValue.i8;
   1056         allowed_vals->i8step = opd.FORM.Range.StepSize.i8;
   1057         allowed_vals->datatype = LIBMTP_DATATYPE_INT8;
   1058         break;
   1059       case PTP_DTC_UINT8:
   1060         allowed_vals->u8min = opd.FORM.Range.MinimumValue.u8;
   1061         allowed_vals->u8max = opd.FORM.Range.MaximumValue.u8;
   1062         allowed_vals->u8step = opd.FORM.Range.StepSize.u8;
   1063         allowed_vals->datatype = LIBMTP_DATATYPE_UINT8;
   1064         break;
   1065       case PTP_DTC_INT16:
   1066         allowed_vals->i16min = opd.FORM.Range.MinimumValue.i16;
   1067         allowed_vals->i16max = opd.FORM.Range.MaximumValue.i16;
   1068         allowed_vals->i16step = opd.FORM.Range.StepSize.i16;
   1069         allowed_vals->datatype = LIBMTP_DATATYPE_INT16;
   1070         break;
   1071       case PTP_DTC_UINT16:
   1072         allowed_vals->u16min = opd.FORM.Range.MinimumValue.u16;
   1073         allowed_vals->u16max = opd.FORM.Range.MaximumValue.u16;
   1074         allowed_vals->u16step = opd.FORM.Range.StepSize.u16;
   1075         allowed_vals->datatype = LIBMTP_DATATYPE_UINT16;
   1076         break;
   1077       case PTP_DTC_INT32:
   1078         allowed_vals->i32min = opd.FORM.Range.MinimumValue.i32;
   1079         allowed_vals->i32max = opd.FORM.Range.MaximumValue.i32;
   1080         allowed_vals->i32step = opd.FORM.Range.StepSize.i32;
   1081         allowed_vals->datatype = LIBMTP_DATATYPE_INT32;
   1082         break;
   1083       case PTP_DTC_UINT32:
   1084         allowed_vals->u32min = opd.FORM.Range.MinimumValue.u32;
   1085         allowed_vals->u32max = opd.FORM.Range.MaximumValue.u32;
   1086         allowed_vals->u32step = opd.FORM.Range.StepSize.u32;
   1087         allowed_vals->datatype = LIBMTP_DATATYPE_UINT32;
   1088         break;
   1089       case PTP_DTC_INT64:
   1090         allowed_vals->i64min = opd.FORM.Range.MinimumValue.i64;
   1091         allowed_vals->i64max = opd.FORM.Range.MaximumValue.i64;
   1092         allowed_vals->i64step = opd.FORM.Range.StepSize.i64;
   1093         allowed_vals->datatype = LIBMTP_DATATYPE_INT64;
   1094         break;
   1095       case PTP_DTC_UINT64:
   1096         allowed_vals->u64min = opd.FORM.Range.MinimumValue.u64;
   1097         allowed_vals->u64max = opd.FORM.Range.MaximumValue.u64;
   1098         allowed_vals->u64step = opd.FORM.Range.StepSize.u64;
   1099         allowed_vals->datatype = LIBMTP_DATATYPE_UINT64;
   1100         break;
   1101     }
   1102     return 0;
   1103   } else
   1104     return -1;
   1105 }
   1106 
   1107 /**
   1108  * Destroys a LIBMTP_allowed_values_t struct
   1109  * @param allowed_vals the struct to destroy
   1110  */
   1111 void LIBMTP_destroy_allowed_values_t(LIBMTP_allowed_values_t *allowed_vals)
   1112 {
   1113   if (!allowed_vals->is_range)
   1114   {
   1115     switch (allowed_vals->datatype)
   1116     {
   1117       case LIBMTP_DATATYPE_INT8:
   1118         if (allowed_vals->i8vals)
   1119           free(allowed_vals->i8vals);
   1120         break;
   1121       case LIBMTP_DATATYPE_UINT8:
   1122         if (allowed_vals->u8vals)
   1123           free(allowed_vals->u8vals);
   1124         break;
   1125       case LIBMTP_DATATYPE_INT16:
   1126         if (allowed_vals->i16vals)
   1127           free(allowed_vals->i16vals);
   1128         break;
   1129       case LIBMTP_DATATYPE_UINT16:
   1130         if (allowed_vals->u16vals)
   1131           free(allowed_vals->u16vals);
   1132         break;
   1133       case LIBMTP_DATATYPE_INT32:
   1134         if (allowed_vals->i32vals)
   1135           free(allowed_vals->i32vals);
   1136         break;
   1137       case LIBMTP_DATATYPE_UINT32:
   1138         if (allowed_vals->u32vals)
   1139           free(allowed_vals->u32vals);
   1140         break;
   1141       case LIBMTP_DATATYPE_INT64:
   1142         if (allowed_vals->i64vals)
   1143           free(allowed_vals->i64vals);
   1144         break;
   1145       case LIBMTP_DATATYPE_UINT64:
   1146         if (allowed_vals->u64vals)
   1147           free(allowed_vals->u64vals);
   1148         break;
   1149     }
   1150   }
   1151 }
   1152 
   1153 /**
   1154  * Determine if a property is supported for a given file type
   1155  * @param device a pointer to an MTP device
   1156  * @param property the property to query
   1157  * @param filetype the filetype of the object you want to set values for
   1158  * @return 0 if not supported, positive if supported, negative on error
   1159  */
   1160 int LIBMTP_Is_Property_Supported(LIBMTP_mtpdevice_t *device, LIBMTP_property_t const property,
   1161             LIBMTP_filetype_t const filetype)
   1162 {
   1163   uint16_t *props = NULL;
   1164   uint32_t propcnt = 0;
   1165   uint16_t ret = 0;
   1166   int i = 0;
   1167   int supported = 0;
   1168   uint16_t ptp_prop = map_libmtp_property_to_ptp_property(property);
   1169 
   1170   if (!ptp_operation_issupported(device->params, PTP_OC_MTP_GetObjectPropsSupported))
   1171     return 0;
   1172 
   1173   ret = ptp_mtp_getobjectpropssupported(device->params, map_libmtp_type_to_ptp_type(filetype), &propcnt, &props);
   1174   if (ret != PTP_RC_OK) {
   1175     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Is_Property_Supported(): could not get properties supported.");
   1176     return -1;
   1177   }
   1178 
   1179 	for (i = 0; i < propcnt; i++) {
   1180     if (props[i] == ptp_prop) {
   1181       supported = 1;
   1182       break;
   1183     }
   1184   }
   1185 
   1186   free(props);
   1187 
   1188   return supported;
   1189 }
   1190 
   1191 /**
   1192  * Retrieves a string from an object
   1193  *
   1194  * @param device a pointer to an MTP device.
   1195  * @param object_id Object reference
   1196  * @param attribute_id MTP attribute ID
   1197  * @return valid string or NULL on failure. The returned string
   1198  *         must bee <code>free()</code>:ed by the caller after
   1199  *         use.
   1200  */
   1201 char *LIBMTP_Get_String_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1202 				    LIBMTP_property_t const attribute_id)
   1203 {
   1204   return get_string_from_object(device, object_id, attribute_id);
   1205 }
   1206 
   1207 /**
   1208 * Retrieves an unsigned 64-bit integer from an object attribute
   1209  *
   1210  * @param device a pointer to an MTP device.
   1211  * @param object_id Object reference
   1212  * @param attribute_id MTP attribute ID
   1213  * @param value_default Default value to return on failure
   1214  * @return the value
   1215  */
   1216 uint64_t LIBMTP_Get_u64_From_Object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
   1217                                     LIBMTP_property_t const attribute_id, uint64_t const value_default)
   1218 {
   1219   return get_u64_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
   1220 }
   1221 
   1222 /**
   1223  * Retrieves an unsigned 32-bit integer from an object attribute
   1224  *
   1225  * @param device a pointer to an MTP device.
   1226  * @param object_id Object reference
   1227  * @param attribute_id MTP attribute ID
   1228  * @param value_default Default value to return on failure
   1229  * @return the value
   1230  */
   1231 uint32_t LIBMTP_Get_u32_From_Object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
   1232 				    LIBMTP_property_t const attribute_id, uint32_t const value_default)
   1233 {
   1234   return get_u32_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
   1235 }
   1236 
   1237 /**
   1238  * Retrieves an unsigned 16-bit integer from an object attribute
   1239  *
   1240  * @param device a pointer to an MTP device.
   1241  * @param object_id Object reference
   1242  * @param attribute_id MTP attribute ID
   1243  * @param value_default Default value to return on failure
   1244  * @return a value
   1245  */
   1246 uint16_t LIBMTP_Get_u16_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1247 				    LIBMTP_property_t const attribute_id, uint16_t const value_default)
   1248 {
   1249   return get_u16_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
   1250 }
   1251 
   1252 /**
   1253  * Retrieves an unsigned 8-bit integer from an object attribute
   1254  *
   1255  * @param device a pointer to an MTP device.
   1256  * @param object_id Object reference
   1257  * @param attribute_id MTP attribute ID
   1258  * @param value_default Default value to return on failure
   1259  * @return a value
   1260  */
   1261 uint8_t LIBMTP_Get_u8_From_Object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1262 				  LIBMTP_property_t const attribute_id, uint8_t const value_default)
   1263 {
   1264   return get_u8_from_object(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value_default);
   1265 }
   1266 
   1267 /**
   1268  * Sets an object attribute from a string
   1269  *
   1270  * @param device a pointer to an MTP device.
   1271  * @param object_id Object reference
   1272  * @param attribute_id MTP attribute ID
   1273  * @param string string value to set
   1274  * @return 0 on success, any other value means failure
   1275  */
   1276 int LIBMTP_Set_Object_String(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1277 			     LIBMTP_property_t const attribute_id, char const * const string)
   1278 {
   1279   return set_object_string(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), string);
   1280 }
   1281 
   1282 
   1283 /**
   1284  * Sets an object attribute from an unsigned 32-bit integer
   1285  *
   1286  * @param device a pointer to an MTP device.
   1287  * @param object_id Object reference
   1288  * @param attribute_id MTP attribute ID
   1289  * @param value 32-bit unsigned integer to set
   1290  * @return 0 on success, any other value means failure
   1291  */
   1292 int LIBMTP_Set_Object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1293 			  LIBMTP_property_t const attribute_id, uint32_t const value)
   1294 {
   1295   return set_object_u32(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
   1296 }
   1297 
   1298 /**
   1299  * Sets an object attribute from an unsigned 16-bit integer
   1300  *
   1301  * @param device a pointer to an MTP device.
   1302  * @param object_id Object reference
   1303  * @param attribute_id MTP attribute ID
   1304  * @param value 16-bit unsigned integer to set
   1305  * @return 0 on success, any other value means failure
   1306  */
   1307 int LIBMTP_Set_Object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1308 			  LIBMTP_property_t const attribute_id, uint16_t const value)
   1309 {
   1310   return set_object_u16(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
   1311 }
   1312 
   1313 /**
   1314  * Sets an object attribute from an unsigned 8-bit integer
   1315  *
   1316  * @param device a pointer to an MTP device.
   1317  * @param object_id Object reference
   1318  * @param attribute_id MTP attribute ID
   1319  * @param value 8-bit unsigned integer to set
   1320  * @return 0 on success, any other value means failure
   1321  */
   1322 int LIBMTP_Set_Object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1323 			 LIBMTP_property_t const attribute_id, uint8_t const value)
   1324 {
   1325   return set_object_u8(device, object_id, map_libmtp_property_to_ptp_property(attribute_id), value);
   1326 }
   1327 
   1328 /**
   1329  * Retrieves a string from an object
   1330  *
   1331  * @param device a pointer to an MTP device.
   1332  * @param object_id Object reference
   1333  * @param attribute_id PTP attribute ID
   1334  * @return valid string or NULL on failure. The returned string
   1335  *         must bee <code>free()</code>:ed by the caller after
   1336  *         use.
   1337  */
   1338 static char *get_string_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1339 				    uint16_t const attribute_id)
   1340 {
   1341   PTPPropertyValue propval;
   1342   char *retstring = NULL;
   1343   PTPParams *params;
   1344   uint16_t ret;
   1345   MTPProperties *prop;
   1346 
   1347   if (!device || !object_id)
   1348     return NULL;
   1349 
   1350   params = (PTPParams *) device->params;
   1351 
   1352   prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
   1353   if (prop) {
   1354     if (prop->propval.str != NULL)
   1355       return strdup(prop->propval.str);
   1356     else
   1357       return NULL;
   1358   }
   1359 
   1360   ret = ptp_mtp_getobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_STR);
   1361   if (ret == PTP_RC_OK) {
   1362     if (propval.str != NULL) {
   1363       retstring = (char *) strdup(propval.str);
   1364       free(propval.str);
   1365     }
   1366   } else {
   1367     add_ptp_error_to_errorstack(device, ret, "get_string_from_object(): could not get object string.");
   1368   }
   1369 
   1370   return retstring;
   1371 }
   1372 
   1373 /**
   1374 * Retrieves an unsigned 64-bit integer from an object attribute
   1375  *
   1376  * @param device a pointer to an MTP device.
   1377  * @param object_id Object reference
   1378  * @param attribute_id PTP attribute ID
   1379  * @param value_default Default value to return on failure
   1380  * @return the value
   1381  */
   1382 static uint64_t get_u64_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
   1383                                     uint16_t const attribute_id, uint64_t const value_default)
   1384 {
   1385   PTPPropertyValue propval;
   1386   uint64_t retval = value_default;
   1387   PTPParams *params;
   1388   uint16_t ret;
   1389   MTPProperties *prop;
   1390 
   1391   if (!device)
   1392     return value_default;
   1393 
   1394   params = (PTPParams *) device->params;
   1395 
   1396   prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
   1397   if (prop)
   1398     return prop->propval.u64;
   1399 
   1400   ret = ptp_mtp_getobjectpropvalue(params, object_id,
   1401                                    attribute_id,
   1402                                    &propval,
   1403                                    PTP_DTC_UINT64);
   1404   if (ret == PTP_RC_OK) {
   1405     retval = propval.u64;
   1406   } else {
   1407     add_ptp_error_to_errorstack(device, ret, "get_u64_from_object(): could not get unsigned 64bit integer from object.");
   1408   }
   1409 
   1410   return retval;
   1411 }
   1412 
   1413 /**
   1414  * Retrieves an unsigned 32-bit integer from an object attribute
   1415  *
   1416  * @param device a pointer to an MTP device.
   1417  * @param object_id Object reference
   1418  * @param attribute_id PTP attribute ID
   1419  * @param value_default Default value to return on failure
   1420  * @return the value
   1421  */
   1422 static uint32_t get_u32_from_object(LIBMTP_mtpdevice_t *device,uint32_t const object_id,
   1423 				    uint16_t const attribute_id, uint32_t const value_default)
   1424 {
   1425   PTPPropertyValue propval;
   1426   uint32_t retval = value_default;
   1427   PTPParams *params;
   1428   uint16_t ret;
   1429   MTPProperties *prop;
   1430 
   1431   if (!device)
   1432     return value_default;
   1433 
   1434   params = (PTPParams *) device->params;
   1435 
   1436   prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
   1437   if (prop)
   1438     return prop->propval.u32;
   1439 
   1440   ret = ptp_mtp_getobjectpropvalue(params, object_id,
   1441                                    attribute_id,
   1442                                    &propval,
   1443                                    PTP_DTC_UINT32);
   1444   if (ret == PTP_RC_OK) {
   1445     retval = propval.u32;
   1446   } else {
   1447     add_ptp_error_to_errorstack(device, ret, "get_u32_from_object(): could not get unsigned 32bit integer from object.");
   1448   }
   1449   return retval;
   1450 }
   1451 
   1452 /**
   1453  * Retrieves an unsigned 16-bit integer from an object attribute
   1454  *
   1455  * @param device a pointer to an MTP device.
   1456  * @param object_id Object reference
   1457  * @param attribute_id PTP attribute ID
   1458  * @param value_default Default value to return on failure
   1459  * @return a value
   1460  */
   1461 static uint16_t get_u16_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1462 				    uint16_t const attribute_id, uint16_t const value_default)
   1463 {
   1464   PTPPropertyValue propval;
   1465   uint16_t retval = value_default;
   1466   PTPParams *params;
   1467   uint16_t ret;
   1468   MTPProperties *prop;
   1469 
   1470   if (!device)
   1471     return value_default;
   1472 
   1473   params = (PTPParams *) device->params;
   1474 
   1475   // This O(n) search should not be used so often, since code
   1476   // using the cached properties don't usually call this function.
   1477   prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
   1478   if (prop)
   1479     return prop->propval.u16;
   1480 
   1481   ret = ptp_mtp_getobjectpropvalue(params, object_id,
   1482                                    attribute_id,
   1483                                    &propval,
   1484                                    PTP_DTC_UINT16);
   1485   if (ret == PTP_RC_OK) {
   1486     retval = propval.u16;
   1487   } else {
   1488     add_ptp_error_to_errorstack(device, ret, "get_u16_from_object(): could not get unsigned 16bit integer from object.");
   1489   }
   1490 
   1491   return retval;
   1492 }
   1493 
   1494 /**
   1495  * Retrieves an unsigned 8-bit integer from an object attribute
   1496  *
   1497  * @param device a pointer to an MTP device.
   1498  * @param object_id Object reference
   1499  * @param attribute_id PTP attribute ID
   1500  * @param value_default Default value to return on failure
   1501  * @return a value
   1502  */
   1503 static uint8_t get_u8_from_object(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1504 				  uint16_t const attribute_id, uint8_t const value_default)
   1505 {
   1506   PTPPropertyValue propval;
   1507   uint8_t retval = value_default;
   1508   PTPParams *params;
   1509   uint16_t ret;
   1510   MTPProperties *prop;
   1511 
   1512   if (!device)
   1513     return value_default;
   1514 
   1515   params = (PTPParams *) device->params;
   1516 
   1517   // This O(n) search should not be used so often, since code
   1518   // using the cached properties don't usually call this function.
   1519   prop = ptp_find_object_prop_in_cache(params, object_id, attribute_id);
   1520   if (prop)
   1521     return prop->propval.u8;
   1522 
   1523   ret = ptp_mtp_getobjectpropvalue(params, object_id,
   1524                                    attribute_id,
   1525                                    &propval,
   1526                                    PTP_DTC_UINT8);
   1527   if (ret == PTP_RC_OK) {
   1528     retval = propval.u8;
   1529   } else {
   1530     add_ptp_error_to_errorstack(device, ret, "get_u8_from_object(): could not get unsigned 8bit integer from object.");
   1531   }
   1532 
   1533   return retval;
   1534 }
   1535 
   1536 /**
   1537  * Sets an object attribute from a string
   1538  *
   1539  * @param device a pointer to an MTP device.
   1540  * @param object_id Object reference
   1541  * @param attribute_id PTP attribute ID
   1542  * @param string string value to set
   1543  * @return 0 on success, any other value means failure
   1544  */
   1545 static int set_object_string(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1546 			     uint16_t const attribute_id, char const * const string)
   1547 {
   1548   PTPPropertyValue propval;
   1549   PTPParams *params;
   1550   uint16_t ret;
   1551 
   1552   if (!device || !string)
   1553     return -1;
   1554 
   1555   params = (PTPParams *) device->params;
   1556 
   1557   if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
   1558     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_string(): could not set object string: "
   1559 				"PTP_OC_MTP_SetObjectPropValue not supported.");
   1560     return -1;
   1561   }
   1562   propval.str = (char *) string;
   1563   ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_STR);
   1564   if (ret != PTP_RC_OK) {
   1565     add_ptp_error_to_errorstack(device, ret, "set_object_string(): could not set object string.");
   1566     return -1;
   1567   }
   1568 
   1569   return 0;
   1570 }
   1571 
   1572 
   1573 /**
   1574  * Sets an object attribute from an unsigned 32-bit integer
   1575  *
   1576  * @param device a pointer to an MTP device.
   1577  * @param object_id Object reference
   1578  * @param attribute_id PTP attribute ID
   1579  * @param value 32-bit unsigned integer to set
   1580  * @return 0 on success, any other value means failure
   1581  */
   1582 static int set_object_u32(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1583 			  uint16_t const attribute_id, uint32_t const value)
   1584 {
   1585   PTPPropertyValue propval;
   1586   PTPParams *params;
   1587   uint16_t ret;
   1588 
   1589   if (!device)
   1590     return -1;
   1591 
   1592   params = (PTPParams *) device->params;
   1593 
   1594   if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
   1595     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u32(): could not set unsigned 32bit integer property: "
   1596 				"PTP_OC_MTP_SetObjectPropValue not supported.");
   1597     return -1;
   1598   }
   1599 
   1600   propval.u32 = value;
   1601   ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT32);
   1602   if (ret != PTP_RC_OK) {
   1603     add_ptp_error_to_errorstack(device, ret, "set_object_u32(): could not set unsigned 32bit integer property.");
   1604     return -1;
   1605   }
   1606 
   1607   return 0;
   1608 }
   1609 
   1610 /**
   1611  * Sets an object attribute from an unsigned 16-bit integer
   1612  *
   1613  * @param device a pointer to an MTP device.
   1614  * @param object_id Object reference
   1615  * @param attribute_id PTP attribute ID
   1616  * @param value 16-bit unsigned integer to set
   1617  * @return 0 on success, any other value means failure
   1618  */
   1619 static int set_object_u16(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1620 			  uint16_t const attribute_id, uint16_t const value)
   1621 {
   1622   PTPPropertyValue propval;
   1623   PTPParams *params;
   1624   uint16_t ret;
   1625 
   1626   if (!device)
   1627     return 1;
   1628 
   1629   params = (PTPParams *) device->params;
   1630 
   1631   if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
   1632     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u16(): could not set unsigned 16bit integer property: "
   1633 				"PTP_OC_MTP_SetObjectPropValue not supported.");
   1634     return -1;
   1635   }
   1636   propval.u16 = value;
   1637   ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT16);
   1638   if (ret != PTP_RC_OK) {
   1639     add_ptp_error_to_errorstack(device, ret, "set_object_u16(): could not set unsigned 16bit integer property.");
   1640     return 1;
   1641   }
   1642 
   1643   return 0;
   1644 }
   1645 
   1646 /**
   1647  * Sets an object attribute from an unsigned 8-bit integer
   1648  *
   1649  * @param device a pointer to an MTP device.
   1650  * @param object_id Object reference
   1651  * @param attribute_id PTP attribute ID
   1652  * @param value 8-bit unsigned integer to set
   1653  * @return 0 on success, any other value means failure
   1654  */
   1655 static int set_object_u8(LIBMTP_mtpdevice_t *device, uint32_t const object_id,
   1656 			 uint16_t const attribute_id, uint8_t const value)
   1657 {
   1658   PTPPropertyValue propval;
   1659   PTPParams *params;
   1660   uint16_t ret;
   1661 
   1662   if (!device)
   1663     return 1;
   1664 
   1665   params = (PTPParams *) device->params;
   1666 
   1667   if (!ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
   1668     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_u8(): could not set unsigned 8bit integer property: "
   1669 			    "PTP_OC_MTP_SetObjectPropValue not supported.");
   1670     return -1;
   1671   }
   1672   propval.u8 = value;
   1673   ret = ptp_mtp_setobjectpropvalue(params, object_id, attribute_id, &propval, PTP_DTC_UINT8);
   1674   if (ret != PTP_RC_OK) {
   1675     add_ptp_error_to_errorstack(device, ret, "set_object_u8(): could not set unsigned 8bit integer property.");
   1676     return 1;
   1677   }
   1678 
   1679   return 0;
   1680 }
   1681 
   1682 /**
   1683  * Get the first (as in "first in the list of") connected MTP device.
   1684  * @return a device pointer.
   1685  * @see LIBMTP_Get_Connected_Devices()
   1686  */
   1687 LIBMTP_mtpdevice_t *LIBMTP_Get_First_Device(void)
   1688 {
   1689   LIBMTP_mtpdevice_t *first_device = NULL;
   1690   LIBMTP_raw_device_t *devices;
   1691   int numdevs;
   1692   LIBMTP_error_number_t ret;
   1693 
   1694   ret = LIBMTP_Detect_Raw_Devices(&devices, &numdevs);
   1695   if (ret != LIBMTP_ERROR_NONE) {
   1696     return NULL;
   1697   }
   1698 
   1699   if (devices == NULL || numdevs == 0) {
   1700     free(devices);
   1701     return NULL;
   1702   }
   1703 
   1704   first_device = LIBMTP_Open_Raw_Device(&devices[0]);
   1705   free(devices);
   1706   return first_device;
   1707 }
   1708 
   1709 /**
   1710  * Overriding debug function.
   1711  * This way we can disable debug prints.
   1712  */
   1713 static void
   1714 #ifdef __GNUC__
   1715 __attribute__((__format__(printf,2,0)))
   1716 #endif
   1717 LIBMTP_ptp_debug(void *data, const char *format, va_list args)
   1718 {
   1719   if ((LIBMTP_debug & LIBMTP_DEBUG_PTP) != 0) {
   1720     vfprintf (stderr, format, args);
   1721     fprintf (stderr, "\n");
   1722     fflush (stderr);
   1723   }
   1724 }
   1725 
   1726 /**
   1727  * Overriding error function.
   1728  * This way we can capture all error etc to our errorstack.
   1729  */
   1730 static void
   1731 #ifdef __GNUC__
   1732 __attribute__((__format__(printf,2,0)))
   1733 #endif
   1734 LIBMTP_ptp_error(void *data, const char *format, va_list args)
   1735 {
   1736   // if (data == NULL) {
   1737     vfprintf (stderr, format, args);
   1738     fflush (stderr);
   1739   /*
   1740     FIXME: find out how we shall get the device here.
   1741   } else {
   1742     PTP_USB *ptp_usb = data;
   1743     LIBMTP_mtpdevice_t *device = ...;
   1744     char buf[2048];
   1745 
   1746     vsnprintf (buf, sizeof (buf), format, args);
   1747     add_error_to_errorstack(device,
   1748 			    LIBMTP_ERROR_PTP_LAYER,
   1749 			    buf);
   1750   }
   1751   */
   1752 }
   1753 
   1754 /**
   1755  * Parses the extension descriptor, there may be stuff in
   1756  * this that we want to know about.
   1757  */
   1758 static void parse_extension_descriptor(LIBMTP_mtpdevice_t *mtpdevice,
   1759                                        char *desc)
   1760 {
   1761   int start = 0;
   1762   int end = 0;
   1763 
   1764   /* NULL on Canon A70 */
   1765   if (!desc)
   1766     return;
   1767 
   1768   /* descriptors are divided by semicolons */
   1769   while (end < strlen(desc)) {
   1770     /* Skip past initial whitespace */
   1771     while ((end < strlen(desc)) && (desc[start] == ' ' )) {
   1772       start++;
   1773       end++;
   1774     }
   1775     /* Detect extension */
   1776     while ((end < strlen(desc)) && (desc[end] != ';'))
   1777       end++;
   1778     if (end < strlen(desc)) {
   1779       char *element = strndup(desc + start, end-start);
   1780       if (element) {
   1781         int i = 0;
   1782         // printf("  Element: \"%s\"\n", element);
   1783 
   1784         /* Parse for an extension */
   1785         while ((i < strlen(element)) && (element[i] != ':'))
   1786           i++;
   1787         if (i < strlen(element)) {
   1788           char *name = strndup(element, i);
   1789           int major = 0, minor = 0;
   1790 
   1791 	  /* extension versions have to be MAJOR.MINOR, but Samsung has one
   1792 	   * with just 0, so just cope with those cases too */
   1793 	  if (	(2 == sscanf(element+i+1,"%d.%d",&major,&minor)) ||
   1794 	  	(1 == sscanf(element+i+1,"%d",&major))
   1795 	  ) {
   1796             LIBMTP_device_extension_t *extension;
   1797 
   1798             extension = malloc(sizeof(LIBMTP_device_extension_t));
   1799             extension->name = name;
   1800             extension->major = major;
   1801             extension->minor = minor;
   1802             extension->next = NULL;
   1803             if (mtpdevice->extensions == NULL) {
   1804               mtpdevice->extensions = extension;
   1805             } else {
   1806               LIBMTP_device_extension_t *tmp = mtpdevice->extensions;
   1807               while (tmp->next != NULL)
   1808                 tmp = tmp->next;
   1809               tmp->next = extension;
   1810             }
   1811           } else {
   1812             LIBMTP_ERROR("LIBMTP ERROR: couldnt parse extension %s\n",
   1813                          element);
   1814           }
   1815         }
   1816         free(element);
   1817       }
   1818     }
   1819     end++;
   1820     start = end;
   1821   }
   1822 }
   1823 
   1824 /**
   1825  * This function opens a device from a raw device. It is the
   1826  * preferred way to access devices in the new interface where
   1827  * several devices can come and go as the library is working
   1828  * on a certain device.
   1829  * @param rawdevice the raw device to open a "real" device for.
   1830  * @return an open device.
   1831  */
   1832 LIBMTP_mtpdevice_t *LIBMTP_Open_Raw_Device_Uncached(LIBMTP_raw_device_t *rawdevice)
   1833 {
   1834   LIBMTP_mtpdevice_t *mtp_device;
   1835   uint8_t bs = 0;
   1836   PTPParams *current_params;
   1837   PTP_USB *ptp_usb;
   1838   LIBMTP_error_number_t err;
   1839   int i;
   1840 
   1841   /* Allocate dynamic space for our device */
   1842   mtp_device = (LIBMTP_mtpdevice_t *) malloc(sizeof(LIBMTP_mtpdevice_t));
   1843   /* Check if there was a memory allocation error */
   1844   if(mtp_device == NULL) {
   1845     /* There has been an memory allocation error. We are going to ignore this
   1846        device and attempt to continue */
   1847 
   1848     /* TODO: This error statement could probably be a bit more robust */
   1849     LIBMTP_ERROR("LIBMTP PANIC: connect_usb_devices encountered a memory "
   1850 	    "allocation error with device %d on bus %d, trying to continue",
   1851 	    rawdevice->devnum, rawdevice->bus_location);
   1852 
   1853     return NULL;
   1854   }
   1855   memset(mtp_device, 0, sizeof(LIBMTP_mtpdevice_t));
   1856   // Non-cached by default
   1857   mtp_device->cached = 0;
   1858 
   1859   /* Create PTP params */
   1860   current_params = (PTPParams *) malloc(sizeof(PTPParams));
   1861   if (current_params == NULL) {
   1862     free(mtp_device);
   1863     return NULL;
   1864   }
   1865   memset(current_params, 0, sizeof(PTPParams));
   1866   current_params->device_flags = rawdevice->device_entry.device_flags;
   1867   current_params->nrofobjects = 0;
   1868   current_params->cachetime = 2;
   1869   current_params->objects = NULL;
   1870   current_params->response_packet_size = 0;
   1871   current_params->response_packet = NULL;
   1872   /* This will be a pointer to PTP_USB later */
   1873   current_params->data = NULL;
   1874   /* Set upp local debug and error functions */
   1875   current_params->debug_func = LIBMTP_ptp_debug;
   1876   current_params->error_func = LIBMTP_ptp_error;
   1877   /* TODO: Will this always be little endian? */
   1878   current_params->byteorder = PTP_DL_LE;
   1879   current_params->cd_locale_to_ucs2 = iconv_open("UCS-2LE", "UTF-8");
   1880   current_params->cd_ucs2_to_locale = iconv_open("UTF-8", "UCS-2LE");
   1881 
   1882   if(current_params->cd_locale_to_ucs2 == (iconv_t) -1 ||
   1883      current_params->cd_ucs2_to_locale == (iconv_t) -1) {
   1884     LIBMTP_ERROR("LIBMTP PANIC: Cannot open iconv() converters to/from UCS-2!\n"
   1885 	    "Too old stdlibc, glibc and libiconv?\n");
   1886     free(current_params);
   1887     free(mtp_device);
   1888     return NULL;
   1889   }
   1890   mtp_device->params = current_params;
   1891 
   1892   /* Create usbinfo, this also opens the session */
   1893   err = configure_usb_device(rawdevice,
   1894 			     current_params,
   1895 			     &mtp_device->usbinfo);
   1896   if (err != LIBMTP_ERROR_NONE) {
   1897     free(current_params);
   1898     free(mtp_device);
   1899     return NULL;
   1900   }
   1901   ptp_usb = (PTP_USB*) mtp_device->usbinfo;
   1902   /* Set pointer back to params */
   1903   ptp_usb->params = current_params;
   1904 
   1905   /* Cache the device information for later use */
   1906   if (ptp_getdeviceinfo(current_params,
   1907 			&current_params->deviceinfo) != PTP_RC_OK) {
   1908     LIBMTP_ERROR("LIBMTP PANIC: Unable to read device information on device "
   1909 	    "%d on bus %d, trying to continue",
   1910 	    rawdevice->devnum, rawdevice->bus_location);
   1911 
   1912     /* Prevent memory leaks for this device */
   1913     free(mtp_device->usbinfo);
   1914     free(mtp_device->params);
   1915     current_params = NULL;
   1916     free(mtp_device);
   1917     return NULL;
   1918   }
   1919 
   1920   /* Check: if this is a PTP device, is it really tagged as MTP? */
   1921   if (current_params->deviceinfo.VendorExtensionID != 0x00000006) {
   1922     LIBMTP_ERROR("LIBMTP WARNING: no MTP vendor extension on device "
   1923 		 "%d on bus %d",
   1924 		 rawdevice->devnum, rawdevice->bus_location);
   1925     LIBMTP_ERROR("LIBMTP WARNING: VendorExtensionID: %08x",
   1926 		 current_params->deviceinfo.VendorExtensionID);
   1927     LIBMTP_ERROR("LIBMTP WARNING: VendorExtensionDesc: %s",
   1928 		 current_params->deviceinfo.VendorExtensionDesc);
   1929     LIBMTP_ERROR("LIBMTP WARNING: this typically means the device is PTP "
   1930 		 "(i.e. a camera) but not an MTP device at all. "
   1931 		 "Trying to continue anyway.");
   1932   }
   1933 
   1934   parse_extension_descriptor(mtp_device,
   1935                              current_params->deviceinfo.VendorExtensionDesc);
   1936 
   1937   /*
   1938    * Android has a number of bugs, force-assign these bug flags
   1939    * if Android is encountered. Same thing for devices we detect
   1940    * as SONY NWZ Walkmen. I have no clue what "sony.net/WMFU" means
   1941    * I just know only NWZs have it.
   1942    */
   1943   {
   1944     LIBMTP_device_extension_t *tmpext = mtp_device->extensions;
   1945     int is_microsoft_com_wpdna = 0;
   1946     int is_android = 0;
   1947     int is_sony_net_wmfu = 0;
   1948     int is_sonyericsson_com_se = 0;
   1949 
   1950     /* Loop over extensions and set flags */
   1951     while (tmpext != NULL) {
   1952       if (!strcmp(tmpext->name, "microsoft.com/WPDNA"))
   1953 	is_microsoft_com_wpdna = 1;
   1954       if (!strcmp(tmpext->name, "android.com"))
   1955 	is_android = 1;
   1956       if (!strcmp(tmpext->name, "sony.net/WMFU"))
   1957 	is_sony_net_wmfu = 1;
   1958       if (!strcmp(tmpext->name, "sonyericsson.com/SE"))
   1959 	is_sonyericsson_com_se = 1;
   1960       tmpext = tmpext->next;
   1961     }
   1962 
   1963     /* Check for specific stacks */
   1964     if (is_microsoft_com_wpdna && is_sonyericsson_com_se && !is_android) {
   1965       /*
   1966        * The Aricent stack seems to be detected by providing WPDNA, the SonyEricsson
   1967        * extension and NO Android extension.
   1968        */
   1969       ptp_usb->rawdevice.device_entry.device_flags |= DEVICE_FLAGS_ARICENT_BUGS;
   1970       LIBMTP_INFO("Aricent MTP stack device detected, assigning default bug flags\n");
   1971     }
   1972     else if (is_android) {
   1973       /*
   1974        * If bugs are fixed in later versions, test on tmpext->major, tmpext->minor
   1975        */
   1976       ptp_usb->rawdevice.device_entry.device_flags |= DEVICE_FLAGS_ANDROID_BUGS;
   1977       LIBMTP_INFO("Android device detected, assigning default bug flags\n");
   1978     }
   1979     else if (is_sony_net_wmfu) {
   1980       ptp_usb->rawdevice.device_entry.device_flags |= DEVICE_FLAGS_SONY_NWZ_BUGS;
   1981       LIBMTP_INFO("SONY NWZ device detected, assigning default bug flags\n");
   1982     }
   1983   }
   1984 
   1985   /*
   1986    * If the OGG or FLAC filetypes are flagged as "unknown", check
   1987    * if the firmware has been updated to actually support it.
   1988    */
   1989   if (FLAG_OGG_IS_UNKNOWN(ptp_usb)) {
   1990     for (i=0;i<current_params->deviceinfo.ImageFormats_len;i++) {
   1991       if (current_params->deviceinfo.ImageFormats[i] == PTP_OFC_MTP_OGG) {
   1992         /* This is not unknown anymore, unflag it */
   1993         ptp_usb->rawdevice.device_entry.device_flags &=
   1994           ~DEVICE_FLAG_OGG_IS_UNKNOWN;
   1995         break;
   1996       }
   1997     }
   1998   }
   1999   if (FLAG_FLAC_IS_UNKNOWN(ptp_usb)) {
   2000     for (i=0;i<current_params->deviceinfo.ImageFormats_len;i++) {
   2001       if (current_params->deviceinfo.ImageFormats[i] == PTP_OFC_MTP_FLAC) {
   2002         /* This is not unknown anymore, unflag it */
   2003         ptp_usb->rawdevice.device_entry.device_flags &=
   2004           ~DEVICE_FLAG_FLAC_IS_UNKNOWN;
   2005         break;
   2006       }
   2007     }
   2008   }
   2009 
   2010   /* Determine if the object size supported is 32 or 64 bit wide */
   2011   if (ptp_operation_issupported(current_params,PTP_OC_MTP_GetObjectPropsSupported)) {
   2012     for (i=0;i<current_params->deviceinfo.ImageFormats_len;i++) {
   2013       PTPObjectPropDesc opd;
   2014 
   2015       if (ptp_mtp_getobjectpropdesc(current_params,
   2016                                     PTP_OPC_ObjectSize,
   2017                                     current_params->deviceinfo.ImageFormats[i],
   2018                                     &opd) != PTP_RC_OK) {
   2019         LIBMTP_ERROR("LIBMTP PANIC: "
   2020                      "could not inspect object property descriptions!\n");
   2021       } else {
   2022         if (opd.DataType == PTP_DTC_UINT32) {
   2023           if (bs == 0) {
   2024             bs = 32;
   2025           } else if (bs != 32) {
   2026             LIBMTP_ERROR("LIBMTP PANIC: "
   2027                          "different objects support different object sizes!\n");
   2028             bs = 0;
   2029             break;
   2030           }
   2031         } else if (opd.DataType == PTP_DTC_UINT64) {
   2032           if (bs == 0) {
   2033             bs = 64;
   2034           } else if (bs != 64) {
   2035             LIBMTP_ERROR("LIBMTP PANIC: "
   2036                          "different objects support different object sizes!\n");
   2037             bs = 0;
   2038             break;
   2039           }
   2040         } else {
   2041           // Ignore if other size.
   2042           LIBMTP_ERROR("LIBMTP PANIC: "
   2043                        "awkward object size data type: %04x\n", opd.DataType);
   2044           bs = 0;
   2045           break;
   2046         }
   2047       }
   2048     }
   2049   }
   2050   if (bs == 0) {
   2051     // Could not detect object bitsize, assume 32 bits
   2052     bs = 32;
   2053   }
   2054   mtp_device->object_bitsize = bs;
   2055 
   2056   /* No Errors yet for this device */
   2057   mtp_device->errorstack = NULL;
   2058 
   2059   /* Default Max Battery Level, we will adjust this if possible */
   2060   mtp_device->maximum_battery_level = 100;
   2061 
   2062   /* Check if device supports reading maximum battery level */
   2063   if(!FLAG_BROKEN_BATTERY_LEVEL(ptp_usb) &&
   2064      ptp_property_issupported( current_params, PTP_DPC_BatteryLevel)) {
   2065     PTPDevicePropDesc dpd;
   2066 
   2067     /* Try to read maximum battery level */
   2068     if(ptp_getdevicepropdesc(current_params,
   2069 			     PTP_DPC_BatteryLevel,
   2070 			     &dpd) != PTP_RC_OK) {
   2071       add_error_to_errorstack(mtp_device,
   2072 			      LIBMTP_ERROR_CONNECTING,
   2073 			      "Unable to read Maximum Battery Level for this "
   2074 			      "device even though the device supposedly "
   2075 			      "supports this functionality");
   2076     }
   2077 
   2078     /* TODO: is this appropriate? */
   2079     /* If max battery level is 0 then leave the default, otherwise assign */
   2080     if (dpd.FORM.Range.MaximumValue.u8 != 0) {
   2081       mtp_device->maximum_battery_level = dpd.FORM.Range.MaximumValue.u8;
   2082     }
   2083 
   2084     ptp_free_devicepropdesc(&dpd);
   2085   }
   2086 
   2087   /* Set all default folders to 0xffffffffU (root directory) */
   2088   mtp_device->default_music_folder = 0xffffffffU;
   2089   mtp_device->default_playlist_folder = 0xffffffffU;
   2090   mtp_device->default_picture_folder = 0xffffffffU;
   2091   mtp_device->default_video_folder = 0xffffffffU;
   2092   mtp_device->default_organizer_folder = 0xffffffffU;
   2093   mtp_device->default_zencast_folder = 0xffffffffU;
   2094   mtp_device->default_album_folder = 0xffffffffU;
   2095   mtp_device->default_text_folder = 0xffffffffU;
   2096 
   2097   /* Set initial storage information */
   2098   mtp_device->storage = NULL;
   2099   if (LIBMTP_Get_Storage(mtp_device, LIBMTP_STORAGE_SORTBY_NOTSORTED) == -1) {
   2100     add_error_to_errorstack(mtp_device,
   2101 			    LIBMTP_ERROR_GENERAL,
   2102 			    "Get Storage information failed.");
   2103     mtp_device->storage = NULL;
   2104   }
   2105 
   2106 
   2107   return mtp_device;
   2108 }
   2109 
   2110 LIBMTP_mtpdevice_t *LIBMTP_Open_Raw_Device(LIBMTP_raw_device_t *rawdevice)
   2111 {
   2112   LIBMTP_mtpdevice_t *mtp_device = LIBMTP_Open_Raw_Device_Uncached(rawdevice);
   2113 
   2114   if (mtp_device == NULL)
   2115     return NULL;
   2116 
   2117   /* Check for MTPZ devices. */
   2118   if (use_mtpz) {
   2119     LIBMTP_device_extension_t *tmpext = mtp_device->extensions;
   2120 
   2121     while (tmpext != NULL) {
   2122       if (!strcmp(tmpext->name, "microsoft.com/MTPZ")) {
   2123 	LIBMTP_INFO("MTPZ device detected. Authenticating...\n");
   2124         if (PTP_RC_OK == ptp_mtpz_handshake(mtp_device->params)) {
   2125 	  LIBMTP_INFO ("(MTPZ) Successfully authenticated with device.\n");
   2126         } else {
   2127           LIBMTP_INFO ("(MTPZ) Failure - could not authenticate with device.\n");
   2128         }
   2129 	break;
   2130       }
   2131       tmpext = tmpext->next;
   2132     }
   2133   }
   2134 
   2135   // Set up this device as cached
   2136   mtp_device->cached = 1;
   2137   /*
   2138    * Then get the handles and try to locate the default folders.
   2139    * This has the desired side effect of caching all handles from
   2140    * the device which speeds up later operations.
   2141    */
   2142   flush_handles(mtp_device);
   2143   return mtp_device;
   2144 }
   2145 
   2146 /**
   2147  * To read events sent by the device, repeatedly call this function from a secondary
   2148  * thread until the return value is < 0.
   2149  *
   2150  * @param device a pointer to the MTP device to poll for events.
   2151  * @param event contains a pointer to be filled in with the event retrieved if the call
   2152  * is successful.
   2153  * @param out1 contains the param1 value from the raw event.
   2154  * @return 0 on success, any other value means the polling loop shall be
   2155  * terminated immediately for this session.
   2156  */
   2157 int LIBMTP_Read_Event(LIBMTP_mtpdevice_t *device, LIBMTP_event_t *event, uint32_t *out1)
   2158 {
   2159   /*
   2160    * FIXME: Potential race-condition here, if client deallocs device
   2161    * while we're *not* waiting for input. As we'll be waiting for
   2162    * input most of the time, it's unlikely but still worth considering
   2163    * for improvement. Also we cannot affect the state of the cache etc
   2164    * unless we know we are the sole user on the device. A spinlock or
   2165    * mutex in the LIBMTP_mtpdevice_t is needed for this to work.
   2166    */
   2167   PTPParams *params = (PTPParams *) device->params;
   2168   PTPContainer ptp_event;
   2169   uint16_t ret = ptp_usb_event_wait(params, &ptp_event);
   2170 
   2171   if (ret != PTP_RC_OK) {
   2172     /* Device is closing down or other fatal stuff, exit thread */
   2173     return -1;
   2174   }
   2175   LIBMTP_Handle_Event(&ptp_event, event, out1);
   2176   return 0;
   2177 }
   2178 
   2179 void LIBMTP_Handle_Event(PTPContainer *ptp_event,
   2180                          LIBMTP_event_t *event, uint32_t *out1) {
   2181   uint16_t code;
   2182   uint32_t session_id;
   2183   uint32_t param1;
   2184 
   2185   *event = LIBMTP_EVENT_NONE;
   2186 
   2187   /* Process the event */
   2188   code = ptp_event->Code;
   2189   session_id = ptp_event->SessionID;
   2190   param1 = ptp_event->Param1;
   2191 
   2192   switch(code) {
   2193     case PTP_EC_Undefined:
   2194       LIBMTP_INFO("Received event PTP_EC_Undefined in session %u\n", session_id);
   2195       break;
   2196     case PTP_EC_CancelTransaction:
   2197       LIBMTP_INFO("Received event PTP_EC_CancelTransaction in session %u\n", session_id);
   2198       break;
   2199     case PTP_EC_ObjectAdded:
   2200       LIBMTP_INFO("Received event PTP_EC_ObjectAdded in session %u\n", session_id);
   2201       *event = LIBMTP_EVENT_OBJECT_ADDED;
   2202       *out1 = param1;
   2203       break;
   2204     case PTP_EC_ObjectRemoved:
   2205       LIBMTP_INFO("Received event PTP_EC_ObjectRemoved in session %u\n", session_id);
   2206       *event = LIBMTP_EVENT_OBJECT_REMOVED;
   2207       *out1 = param1;
   2208       break;
   2209     case PTP_EC_StoreAdded:
   2210       LIBMTP_INFO("Received event PTP_EC_StoreAdded in session %u\n", session_id);
   2211       /* TODO: rescan storages */
   2212       *event = LIBMTP_EVENT_STORE_ADDED;
   2213       *out1 = param1;
   2214       break;
   2215     case PTP_EC_StoreRemoved:
   2216       LIBMTP_INFO("Received event PTP_EC_StoreRemoved in session %u\n", session_id);
   2217       /* TODO: rescan storages */
   2218       *event = LIBMTP_EVENT_STORE_REMOVED;
   2219       *out1 = param1;
   2220       break;
   2221     case PTP_EC_DevicePropChanged:
   2222       LIBMTP_INFO("Received event PTP_EC_DevicePropChanged in session %u\n", session_id);
   2223       /* TODO: update device properties */
   2224       break;
   2225     case PTP_EC_ObjectInfoChanged:
   2226       LIBMTP_INFO("Received event PTP_EC_ObjectInfoChanged in session %u\n", session_id);
   2227       /* TODO: rescan object cache or just for this one object */
   2228       break;
   2229     case PTP_EC_DeviceInfoChanged:
   2230       LIBMTP_INFO("Received event PTP_EC_DeviceInfoChanged in session %u\n", session_id);
   2231       /* TODO: update device info */
   2232       break;
   2233     case PTP_EC_RequestObjectTransfer:
   2234       LIBMTP_INFO("Received event PTP_EC_RequestObjectTransfer in session %u\n", session_id);
   2235       break;
   2236     case PTP_EC_StoreFull:
   2237       LIBMTP_INFO("Received event PTP_EC_StoreFull in session %u\n", session_id);
   2238       break;
   2239     case PTP_EC_DeviceReset:
   2240       LIBMTP_INFO("Received event PTP_EC_DeviceReset in session %u\n", session_id);
   2241       break;
   2242     case PTP_EC_StorageInfoChanged :
   2243       LIBMTP_INFO( "Received event PTP_EC_StorageInfoChanged in session %u\n", session_id);
   2244      /* TODO: update storage info */
   2245       break;
   2246     case PTP_EC_CaptureComplete :
   2247       LIBMTP_INFO( "Received event PTP_EC_CaptureComplete in session %u\n", session_id);
   2248       break;
   2249     case PTP_EC_UnreportedStatus :
   2250       LIBMTP_INFO( "Received event PTP_EC_UnreportedStatus in session %u\n", session_id);
   2251       break;
   2252     default :
   2253       LIBMTP_INFO( "Received unknown event in session %u\n", session_id);
   2254       break;
   2255   }
   2256 }
   2257 
   2258 static void LIBMTP_Read_Event_Cb(PTPParams *params, uint16_t ret_code,
   2259                                  PTPContainer *ptp_event, void *user_data) {
   2260   event_cb_data_t *data = user_data;
   2261   LIBMTP_event_t event = LIBMTP_EVENT_NONE;
   2262   uint32_t param1 = 0;
   2263   int handler_ret;
   2264 
   2265   switch (ret_code) {
   2266   case PTP_RC_OK:
   2267     handler_ret = LIBMTP_HANDLER_RETURN_OK;
   2268     LIBMTP_Handle_Event(ptp_event, &event, &param1);
   2269     break;
   2270   case PTP_ERROR_CANCEL:
   2271     handler_ret = LIBMTP_HANDLER_RETURN_CANCEL;
   2272     break;
   2273   default:
   2274     handler_ret = LIBMTP_HANDLER_RETURN_ERROR;
   2275     break;
   2276   }
   2277 
   2278   data->cb(handler_ret, event, param1, data->user_data);
   2279   free(data);
   2280 }
   2281 
   2282 /**
   2283  * This function reads events sent by the device, in a non-blocking manner.
   2284  * The callback function will be called when an event is received, but for the function
   2285  * to make progress, polling must take place, using LIBMTP_Handle_Events_Timeout_Completed.
   2286  *
   2287  * After an event is received, this function should be called again to listen for the next
   2288  * event.
   2289  *
   2290  * For now, this non-blocking mechanism only works with libusb-1.0, and not any of the
   2291  * other usb library backends. Attempting to call this method with another backend will
   2292  * always return an error.
   2293  *
   2294  * @param device a pointer to the MTP device to poll for events.
   2295  * @param cb a callback to be invoked when an event is received.
   2296  * @param user_data arbitrary user data passed to the callback.
   2297  * @return 0 on success, any other value means that the callback was not registered and
   2298  *         no event notification will take place.
   2299  */
   2300 int LIBMTP_Read_Event_Async(LIBMTP_mtpdevice_t *device, LIBMTP_event_cb_fn cb, void *user_data) {
   2301   PTPParams *params = (PTPParams *) device->params;
   2302   event_cb_data_t *data =  malloc(sizeof(event_cb_data_t));
   2303   uint16_t ret;
   2304 
   2305   data->cb = cb;
   2306   data->user_data = user_data;
   2307 
   2308   ret = ptp_usb_event_async(params, LIBMTP_Read_Event_Cb, data);
   2309   return ret == PTP_RC_OK ? 0 : -1;
   2310 }
   2311 
   2312 /**
   2313  * Recursive function that adds MTP devices to a linked list
   2314  * @param devices a list of raw devices to have real devices created for.
   2315  * @return a device pointer to a newly created mtpdevice (used in linked
   2316  * list creation).
   2317  */
   2318 static LIBMTP_mtpdevice_t * create_usb_mtp_devices(LIBMTP_raw_device_t *devices, int numdevs)
   2319 {
   2320   uint8_t i;
   2321   LIBMTP_mtpdevice_t *mtp_device_list = NULL;
   2322   LIBMTP_mtpdevice_t *current_device = NULL;
   2323 
   2324   for (i=0; i < numdevs; i++) {
   2325     LIBMTP_mtpdevice_t *mtp_device;
   2326     mtp_device = LIBMTP_Open_Raw_Device(&devices[i]);
   2327 
   2328     /* On error, try next device */
   2329     if (mtp_device == NULL)
   2330       continue;
   2331 
   2332     /* Add the device to the list */
   2333     mtp_device->next = NULL;
   2334     if (mtp_device_list == NULL) {
   2335       mtp_device_list = current_device = mtp_device;
   2336     } else {
   2337       current_device->next = mtp_device;
   2338       current_device = mtp_device;
   2339     }
   2340   }
   2341   return mtp_device_list;
   2342 }
   2343 
   2344 /**
   2345  * Get the number of devices that are available in the listed device list
   2346  * @param device_list Pointer to a linked list of devices
   2347  * @return Number of devices in the device list device_list
   2348  * @see LIBMTP_Get_Connected_Devices()
   2349  */
   2350 uint32_t LIBMTP_Number_Devices_In_List(LIBMTP_mtpdevice_t *device_list)
   2351 {
   2352   uint32_t numdevices = 0;
   2353   LIBMTP_mtpdevice_t *iter;
   2354   for(iter = device_list; iter != NULL; iter = iter->next)
   2355     numdevices++;
   2356 
   2357   return numdevices;
   2358 }
   2359 
   2360 /**
   2361  * Get the first connected MTP device node in the linked list of devices.
   2362  * Currently this only provides access to USB devices
   2363  * @param device_list A list of devices ready to be used by the caller. You
   2364  *        need to know how many there are.
   2365  * @return Any error information gathered from device connections
   2366  * @see LIBMTP_Number_Devices_In_List()
   2367  */
   2368 LIBMTP_error_number_t LIBMTP_Get_Connected_Devices(LIBMTP_mtpdevice_t **device_list)
   2369 {
   2370   LIBMTP_raw_device_t *devices;
   2371   int numdevs;
   2372   LIBMTP_error_number_t ret;
   2373 
   2374   ret = LIBMTP_Detect_Raw_Devices(&devices, &numdevs);
   2375   if (ret != LIBMTP_ERROR_NONE) {
   2376     *device_list = NULL;
   2377     return ret;
   2378   }
   2379 
   2380   /* Assign linked list of devices */
   2381   if (devices == NULL || numdevs == 0) {
   2382     *device_list = NULL;
   2383     free(devices);
   2384     return LIBMTP_ERROR_NO_DEVICE_ATTACHED;
   2385   }
   2386 
   2387   *device_list = create_usb_mtp_devices(devices, numdevs);
   2388   free(devices);
   2389 
   2390   /* TODO: Add wifi device access here */
   2391 
   2392   /* We have found some devices but create failed */
   2393   if (*device_list == NULL)
   2394     return LIBMTP_ERROR_CONNECTING;
   2395 
   2396   return LIBMTP_ERROR_NONE;
   2397 }
   2398 
   2399 /**
   2400  * This closes and releases an allocated MTP device.
   2401  * @param device a pointer to the MTP device to release.
   2402  */
   2403 void LIBMTP_Release_Device_List(LIBMTP_mtpdevice_t *device)
   2404 {
   2405   if(device != NULL)
   2406   {
   2407     if(device->next != NULL)
   2408     {
   2409       LIBMTP_Release_Device_List(device->next);
   2410     }
   2411 
   2412     LIBMTP_Release_Device(device);
   2413   }
   2414 }
   2415 
   2416 /**
   2417  * This closes and releases an allocated MTP device.
   2418  * @param device a pointer to the MTP device to release.
   2419  */
   2420 void LIBMTP_Release_Device(LIBMTP_mtpdevice_t *device)
   2421 {
   2422   PTPParams *params = (PTPParams *) device->params;
   2423   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   2424 
   2425   close_device(ptp_usb, params);
   2426   // Clear error stack
   2427   LIBMTP_Clear_Errorstack(device);
   2428   // Free iconv() converters...
   2429   iconv_close(params->cd_locale_to_ucs2);
   2430   iconv_close(params->cd_ucs2_to_locale);
   2431   free(ptp_usb);
   2432   ptp_free_params(params);
   2433   free(params);
   2434   free_storage_list(device);
   2435   // Free extension list...
   2436   if (device->extensions != NULL) {
   2437     LIBMTP_device_extension_t *tmp = device->extensions;
   2438 
   2439     while (tmp != NULL) {
   2440       LIBMTP_device_extension_t *next = tmp->next;
   2441 
   2442       if (tmp->name)
   2443         free(tmp->name);
   2444       free(tmp);
   2445       tmp = next;
   2446     }
   2447   }
   2448   free(device);
   2449 }
   2450 
   2451 /**
   2452  * This can be used by any libmtp-intrinsic code that
   2453  * need to stack up an error on the stack. You are only
   2454  * supposed to add errors to the error stack using this
   2455  * function, do not create and reference error entries
   2456  * directly.
   2457  */
   2458 static void add_error_to_errorstack(LIBMTP_mtpdevice_t *device,
   2459 				    LIBMTP_error_number_t errornumber,
   2460 				    char const * const error_text)
   2461 {
   2462   LIBMTP_error_t *newerror;
   2463 
   2464   if (device == NULL) {
   2465     LIBMTP_ERROR("LIBMTP PANIC: Trying to add error to a NULL device!\n");
   2466     return;
   2467   }
   2468   newerror = (LIBMTP_error_t *) malloc(sizeof(LIBMTP_error_t));
   2469   newerror->errornumber = errornumber;
   2470   newerror->error_text = strdup(error_text);
   2471   newerror->next = NULL;
   2472   if (device->errorstack == NULL) {
   2473     device->errorstack = newerror;
   2474   } else {
   2475     LIBMTP_error_t *tmp = device->errorstack;
   2476 
   2477     while (tmp->next != NULL) {
   2478       tmp = tmp->next;
   2479     }
   2480     tmp->next = newerror;
   2481   }
   2482 }
   2483 
   2484 /**
   2485  * Adds an error from the PTP layer to the error stack.
   2486  */
   2487 static void add_ptp_error_to_errorstack(LIBMTP_mtpdevice_t *device,
   2488 					uint16_t ptp_error,
   2489 					char const * const error_text)
   2490 {
   2491   PTPParams      *params = (PTPParams *) device->params;
   2492 
   2493   if (device == NULL) {
   2494     LIBMTP_ERROR("LIBMTP PANIC: Trying to add PTP error to a NULL device!\n");
   2495     return;
   2496   } else {
   2497     char outstr[256];
   2498     snprintf(outstr, sizeof(outstr), "PTP Layer error %04x: %s", ptp_error, error_text);
   2499     outstr[sizeof(outstr)-1] = '\0';
   2500     add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr);
   2501 
   2502     snprintf(outstr, sizeof(outstr), "Error %04x: %s", ptp_error, ptp_strerror(ptp_error, params->deviceinfo.VendorExtensionID));
   2503     outstr[sizeof(outstr)-1] = '\0';
   2504     add_error_to_errorstack(device, LIBMTP_ERROR_PTP_LAYER, outstr);
   2505   }
   2506 }
   2507 
   2508 /**
   2509  * This returns the error stack for a device in case you
   2510  * need to either reference the error numbers (e.g. when
   2511  * creating multilingual apps with multiple-language text
   2512  * representations for each error number) or when you need
   2513  * to build a multi-line error text widget or something like
   2514  * that. You need to call the <code>LIBMTP_Clear_Errorstack</code>
   2515  * to clear it when you're finished with it.
   2516  * @param device a pointer to the MTP device to get the error
   2517  *        stack for.
   2518  * @return the error stack or NULL if there are no errors
   2519  *         on the stack.
   2520  * @see LIBMTP_Clear_Errorstack()
   2521  * @see LIBMTP_Dump_Errorstack()
   2522  */
   2523 LIBMTP_error_t *LIBMTP_Get_Errorstack(LIBMTP_mtpdevice_t *device)
   2524 {
   2525   if (device == NULL) {
   2526     LIBMTP_ERROR("LIBMTP PANIC: Trying to get the error stack of a NULL device!\n");
   2527     return NULL;
   2528   }
   2529   return device->errorstack;
   2530 }
   2531 
   2532 /**
   2533  * This function clears the error stack of a device and frees
   2534  * any memory used by it. Call this when you're finished with
   2535  * using the errors.
   2536  * @param device a pointer to the MTP device to clear the error
   2537  *        stack for.
   2538  */
   2539 void LIBMTP_Clear_Errorstack(LIBMTP_mtpdevice_t *device)
   2540 {
   2541   if (device == NULL) {
   2542     LIBMTP_ERROR("LIBMTP PANIC: Trying to clear the error stack of a NULL device!\n");
   2543   } else {
   2544     LIBMTP_error_t *tmp = device->errorstack;
   2545 
   2546     while (tmp != NULL) {
   2547       LIBMTP_error_t *tmp2;
   2548 
   2549       if (tmp->error_text != NULL) {
   2550 	free(tmp->error_text);
   2551       }
   2552       tmp2 = tmp;
   2553       tmp = tmp->next;
   2554       free(tmp2);
   2555     }
   2556     device->errorstack = NULL;
   2557   }
   2558 }
   2559 
   2560 /**
   2561  * This function dumps the error stack to <code>stderr</code>.
   2562  * (You still have to clear the stack though.)
   2563  * @param device a pointer to the MTP device to dump the error
   2564  *        stack for.
   2565  */
   2566 void LIBMTP_Dump_Errorstack(LIBMTP_mtpdevice_t *device)
   2567 {
   2568   if (device == NULL) {
   2569     LIBMTP_ERROR("LIBMTP PANIC: Trying to dump the error stack of a NULL device!\n");
   2570   } else {
   2571     LIBMTP_error_t *tmp = device->errorstack;
   2572 
   2573     while (tmp != NULL) {
   2574       if (tmp->error_text != NULL) {
   2575 	LIBMTP_ERROR("Error %d: %s\n", tmp->errornumber, tmp->error_text);
   2576       } else {
   2577 	LIBMTP_ERROR("Error %d: (unknown)\n", tmp->errornumber);
   2578       }
   2579       tmp = tmp->next;
   2580     }
   2581   }
   2582 }
   2583 
   2584 void LIBMTP_Set_Device_Timeout(LIBMTP_mtpdevice_t *device, int milliseconds)
   2585 {
   2586   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   2587   set_usb_device_timeout(ptp_usb, milliseconds);
   2588 }
   2589 
   2590 void LIBMTP_Get_Device_Timeout(LIBMTP_mtpdevice_t *device, int *milliseconds)
   2591 {
   2592   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   2593   get_usb_device_timeout(ptp_usb, milliseconds);
   2594 }
   2595 
   2596 /**
   2597  * This command gets all handles and stuff by FAST directory retrieveal
   2598  * which is available by getting all metadata for object
   2599  * <code>0xffffffff</code> which simply means "all metadata for all objects".
   2600  * This works on the vast majority of MTP devices (there ARE exceptions!)
   2601  * and is quite quick. Check the error stack to see if there were
   2602  * problems getting the metadata.
   2603  * @return 0 if all was OK, -1 on failure.
   2604  */
   2605 static int get_all_metadata_fast(LIBMTP_mtpdevice_t *device)
   2606 {
   2607   PTPParams      *params = (PTPParams *) device->params;
   2608   int		 cnt = 0;
   2609   int            i, j, nrofprops;
   2610   uint32_t	 lasthandle = 0xffffffff;
   2611   MTPProperties  *props = NULL;
   2612   MTPProperties  *prop;
   2613   uint16_t       ret;
   2614   int            oldtimeout;
   2615   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   2616 
   2617   /*
   2618    * The follow request causes the device to generate
   2619    * a list of every file on the device and return it
   2620    * in a single response.
   2621    *
   2622    * Some slow devices as well as devices with very
   2623    * large file systems can easily take longer then
   2624    * the standard timeout value before it is able
   2625    * to return a response.
   2626    *
   2627    * Temporarly set timeout to allow working with
   2628    * widest range of devices.
   2629    */
   2630   get_usb_device_timeout(ptp_usb, &oldtimeout);
   2631   set_usb_device_timeout(ptp_usb, 60000);
   2632 
   2633   ret = ptp_mtp_getobjectproplist(params, 0xffffffff, &props, &nrofprops);
   2634   set_usb_device_timeout(ptp_usb, oldtimeout);
   2635 
   2636   if (ret == PTP_RC_MTP_Specification_By_Group_Unsupported) {
   2637     // What's the point in the device implementing this command if
   2638     // you cannot use it to get all props for AT LEAST one object?
   2639     // Well, whatever...
   2640     add_ptp_error_to_errorstack(device, ret, "get_all_metadata_fast(): "
   2641     "cannot retrieve all metadata for an object on this device.");
   2642     return -1;
   2643   }
   2644   if (ret != PTP_RC_OK) {
   2645     add_ptp_error_to_errorstack(device, ret, "get_all_metadata_fast(): "
   2646     "could not get proplist of all objects.");
   2647     return -1;
   2648   }
   2649   if (props == NULL && nrofprops != 0) {
   2650     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   2651 			    "get_all_metadata_fast(): "
   2652 			    "call to ptp_mtp_getobjectproplist() returned "
   2653 			    "inconsistent results.");
   2654     return -1;
   2655   }
   2656   /*
   2657    * We count the number of objects by counting the ObjectHandle
   2658    * references, whenever it changes we get a new object, when it's
   2659    * the same, it is just different properties of the same object.
   2660    */
   2661   prop = props;
   2662   for (i=0;i<nrofprops;i++) {
   2663       if (lasthandle != prop->ObjectHandle) {
   2664 	cnt++;
   2665 	lasthandle = prop->ObjectHandle;
   2666       }
   2667       prop++;
   2668   }
   2669   lasthandle = 0xffffffff;
   2670   params->objects = calloc (cnt, sizeof(PTPObject));
   2671   prop = props;
   2672   i = -1;
   2673   for (j=0;j<nrofprops;j++) {
   2674     if (lasthandle != prop->ObjectHandle) {
   2675       if (i >= 0) {
   2676         params->objects[i].flags |= PTPOBJECT_OBJECTINFO_LOADED;
   2677 	if (!params->objects[i].oi.Filename) {
   2678 	  /* I have one such file on my Creative (Marcus) */
   2679 	  params->objects[i].oi.Filename = strdup("<null>");
   2680 	}
   2681       }
   2682       i++;
   2683       lasthandle = prop->ObjectHandle;
   2684       params->objects[i].oid = prop->ObjectHandle;
   2685     }
   2686     switch (prop->property) {
   2687     case PTP_OPC_ParentObject:
   2688       params->objects[i].oi.ParentObject = prop->propval.u32;
   2689       params->objects[i].flags |= PTPOBJECT_PARENTOBJECT_LOADED;
   2690       break;
   2691     case PTP_OPC_ObjectFormat:
   2692       params->objects[i].oi.ObjectFormat = prop->propval.u16;
   2693       break;
   2694     case PTP_OPC_ObjectSize:
   2695       // We loose precision here, up to 32 bits! However the commands that
   2696       // retrieve metadata for files and tracks will make sure that the
   2697       // PTP_OPC_ObjectSize is read in and duplicated again.
   2698       if (device->object_bitsize == 64) {
   2699 	params->objects[i].oi.ObjectCompressedSize = (uint32_t) prop->propval.u64;
   2700       } else {
   2701 	params->objects[i].oi.ObjectCompressedSize = prop->propval.u32;
   2702       }
   2703       break;
   2704     case PTP_OPC_StorageID:
   2705       params->objects[i].oi.StorageID = prop->propval.u32;
   2706       params->objects[i].flags |= PTPOBJECT_STORAGEID_LOADED;
   2707       break;
   2708     case PTP_OPC_ObjectFileName:
   2709       if (prop->propval.str != NULL)
   2710         params->objects[i].oi.Filename = strdup(prop->propval.str);
   2711       break;
   2712     default: {
   2713       MTPProperties *newprops;
   2714 
   2715       /* Copy all of the other MTP oprierties into the per-object proplist */
   2716       if (params->objects[i].nrofmtpprops) {
   2717         newprops = realloc(params->objects[i].mtpprops,
   2718 		(params->objects[i].nrofmtpprops+1)*sizeof(MTPProperties));
   2719       } else {
   2720         newprops = calloc(1,sizeof(MTPProperties));
   2721       }
   2722       if (!newprops) return 0; /* FIXME: error handling? */
   2723       params->objects[i].mtpprops = newprops;
   2724       memcpy(&params->objects[i].mtpprops[params->objects[i].nrofmtpprops],
   2725 	     &props[j],sizeof(props[j]));
   2726       params->objects[i].nrofmtpprops++;
   2727       params->objects[i].flags |= PTPOBJECT_MTPPROPLIST_LOADED;
   2728       break;
   2729     }
   2730     }
   2731     prop++;
   2732   }
   2733   /* mark last entry also */
   2734   if (i >= 0) {
   2735     params->objects[i].flags |= PTPOBJECT_OBJECTINFO_LOADED;
   2736     params->nrofobjects = i+1;
   2737   } else {
   2738     params->nrofobjects = 0;
   2739   }
   2740   free (props);
   2741   /* The device might not give the list in linear ascending order */
   2742   ptp_objects_sort (params);
   2743   return 0;
   2744 }
   2745 
   2746 /**
   2747  * This function will recurse through all the directories on the device,
   2748  * starting at the root directory, gathering metadata as it moves along.
   2749  * It works better on some devices that will only return data for a
   2750  * certain directory and does not respect the option to get all metadata
   2751  * for all objects.
   2752  */
   2753 static void get_handles_recursively(LIBMTP_mtpdevice_t *device,
   2754 				    PTPParams *params,
   2755 				    uint32_t storageid,
   2756 				    uint32_t parent)
   2757 {
   2758   PTPObjectHandles currentHandles;
   2759   int i = 0;
   2760   uint16_t ret = ptp_getobjecthandles(params,
   2761                                       storageid,
   2762                                       PTP_GOH_ALL_FORMATS,
   2763                                       parent,
   2764                                       &currentHandles);
   2765 
   2766   if (ret != PTP_RC_OK) {
   2767     add_ptp_error_to_errorstack(device, ret, "get_handles_recursively(): could not get object handles.");
   2768     return;
   2769   }
   2770 
   2771   if (currentHandles.Handler == NULL || currentHandles.n == 0)
   2772     return;
   2773 
   2774   // Now descend into any subdirectories found
   2775   for (i = 0; i < currentHandles.n; i++) {
   2776     PTPObject *ob;
   2777     ret = ptp_object_want(params,currentHandles.Handler[i],
   2778 			  PTPOBJECT_OBJECTINFO_LOADED, &ob);
   2779     if (ret == PTP_RC_OK) {
   2780       if (ob->oi.ObjectFormat == PTP_OFC_Association)
   2781         get_handles_recursively(device, params,
   2782 				storageid, currentHandles.Handler[i]);
   2783     } else {
   2784       add_error_to_errorstack(device,
   2785 			      LIBMTP_ERROR_CONNECTING,
   2786 			      "Found a bad handle, trying to ignore it.");
   2787     }
   2788   }
   2789   free(currentHandles.Handler);
   2790 }
   2791 
   2792 /**
   2793  * This function refresh the internal handle list whenever
   2794  * the items stored inside the device is altered. On operations
   2795  * that do not add or remove objects, this is typically not
   2796  * called.
   2797  * @param device a pointer to the MTP device to flush handles for.
   2798  */
   2799 static void flush_handles(LIBMTP_mtpdevice_t *device)
   2800 {
   2801   PTPParams *params = (PTPParams *) device->params;
   2802   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   2803   int ret;
   2804   uint32_t i;
   2805 
   2806   if (!device->cached) {
   2807     return;
   2808   }
   2809 
   2810   if (load_cache_on_demand) {
   2811     return;
   2812   }
   2813 
   2814   if (params->objects != NULL) {
   2815     for (i=0;i<params->nrofobjects;i++)
   2816       ptp_free_object (&params->objects[i]);
   2817     free(params->objects);
   2818     params->objects = NULL;
   2819     params->nrofobjects = 0;
   2820   }
   2821 
   2822   if (ptp_operation_issupported(params,PTP_OC_MTP_GetObjPropList)
   2823       && !FLAG_BROKEN_MTPGETOBJPROPLIST(ptp_usb)
   2824       && !FLAG_BROKEN_MTPGETOBJPROPLIST_ALL(ptp_usb)) {
   2825     // Use the fast method. Ignore return value for now.
   2826     ret = get_all_metadata_fast(device);
   2827   }
   2828 
   2829   // If the previous failed or returned no objects, use classic
   2830   // methods instead.
   2831   if (params->nrofobjects == 0) {
   2832     // Get all the handles using just standard commands.
   2833     if (device->storage == NULL) {
   2834       get_handles_recursively(device, params,
   2835 			      PTP_GOH_ALL_STORAGE,
   2836 			      PTP_GOH_ROOT_PARENT);
   2837     } else {
   2838       // Get handles for each storage in turn.
   2839       LIBMTP_devicestorage_t *storage = device->storage;
   2840       while(storage != NULL) {
   2841 	get_handles_recursively(device, params,
   2842 				storage->id,
   2843 				PTP_GOH_ROOT_PARENT);
   2844 	storage = storage->next;
   2845       }
   2846     }
   2847   }
   2848 
   2849   /*
   2850    * Loop over the handles, fix up any NULL filenames or
   2851    * keywords, then attempt to locate some default folders
   2852    * in the root directory of the primary storage.
   2853    */
   2854   for(i = 0; i < params->nrofobjects; i++) {
   2855     PTPObject *ob, *xob;
   2856 
   2857     ob = &params->objects[i];
   2858     ret = ptp_object_want(params,params->objects[i].oid,
   2859 			  PTPOBJECT_OBJECTINFO_LOADED, &xob);
   2860     if (ret != PTP_RC_OK) {
   2861 	LIBMTP_ERROR("broken! %x not found\n", params->objects[i].oid);
   2862     }
   2863     if (ob->oi.Filename == NULL)
   2864       ob->oi.Filename = strdup("<null>");
   2865     if (ob->oi.Keywords == NULL)
   2866       ob->oi.Keywords = strdup("<null>");
   2867 
   2868     /* Ignore handles that point to non-folders */
   2869     if(ob->oi.ObjectFormat != PTP_OFC_Association)
   2870       continue;
   2871     /* Only look in the root folder */
   2872     if (ob->oi.ParentObject == 0xffffffffU) {
   2873       LIBMTP_ERROR("object %x has parent 0xffffffff (-1) continuing anyway\n",
   2874 		   ob->oid);
   2875     } else if (ob->oi.ParentObject != 0x00000000U)
   2876       continue;
   2877     /* Only look in the primary storage */
   2878     if (device->storage != NULL && ob->oi.StorageID != device->storage->id)
   2879       continue;
   2880 
   2881     /* Is this the Music Folder */
   2882     if (!strcasecmp(ob->oi.Filename, "My Music") ||
   2883 	!strcasecmp(ob->oi.Filename, "My_Music") ||
   2884 	!strcasecmp(ob->oi.Filename, "Music")) {
   2885       device->default_music_folder = ob->oid;
   2886     }
   2887     else if (!strcasecmp(ob->oi.Filename, "My Playlists") ||
   2888 	     !strcasecmp(ob->oi.Filename, "My_Playlists") ||
   2889 	     !strcasecmp(ob->oi.Filename, "Playlists")) {
   2890       device->default_playlist_folder = ob->oid;
   2891     }
   2892     else if (!strcasecmp(ob->oi.Filename, "My Pictures") ||
   2893 	     !strcasecmp(ob->oi.Filename, "My_Pictures") ||
   2894 	     !strcasecmp(ob->oi.Filename, "Pictures")) {
   2895       device->default_picture_folder = ob->oid;
   2896     }
   2897     else if (!strcasecmp(ob->oi.Filename, "My Video") ||
   2898 	     !strcasecmp(ob->oi.Filename, "My_Video") ||
   2899 	     !strcasecmp(ob->oi.Filename, "Video")) {
   2900 	device->default_video_folder = ob->oid;
   2901     }
   2902     else if (!strcasecmp(ob->oi.Filename, "My Organizer") ||
   2903 	     !strcasecmp(ob->oi.Filename, "My_Organizer")) {
   2904       device->default_organizer_folder = ob->oid;
   2905     }
   2906     else if (!strcasecmp(ob->oi.Filename, "ZENcast") ||
   2907 	     !strcasecmp(ob->oi.Filename, "Datacasts")) {
   2908       device->default_zencast_folder = ob->oid;
   2909     }
   2910     else if (!strcasecmp(ob->oi.Filename, "My Albums") ||
   2911 	     !strcasecmp(ob->oi.Filename, "My_Albums") ||
   2912 	     !strcasecmp(ob->oi.Filename, "Albums")) {
   2913       device->default_album_folder = ob->oid;
   2914     }
   2915     else if (!strcasecmp(ob->oi.Filename, "Text") ||
   2916 	     !strcasecmp(ob->oi.Filename, "Texts")) {
   2917       device->default_text_folder = ob->oid;
   2918     }
   2919   }
   2920 }
   2921 
   2922 /**
   2923  * This function traverses a devices storage list freeing up the
   2924  * strings and the structs.
   2925  * @param device a pointer to the MTP device to free the storage
   2926  * list for.
   2927  */
   2928 static void free_storage_list(LIBMTP_mtpdevice_t *device)
   2929 {
   2930   LIBMTP_devicestorage_t *storage;
   2931   LIBMTP_devicestorage_t *tmp;
   2932 
   2933   storage = device->storage;
   2934   while(storage != NULL) {
   2935     if (storage->StorageDescription != NULL) {
   2936       free(storage->StorageDescription);
   2937     }
   2938     if (storage->VolumeIdentifier != NULL) {
   2939       free(storage->VolumeIdentifier);
   2940     }
   2941     tmp = storage;
   2942     storage = storage->next;
   2943     free(tmp);
   2944   }
   2945   device->storage = NULL;
   2946 
   2947   return;
   2948 }
   2949 
   2950 /**
   2951  * This function traverses a devices storage list freeing up the
   2952  * strings and the structs.
   2953  * @param device a pointer to the MTP device to free the storage
   2954  * list for.
   2955  */
   2956 static int sort_storage_by(LIBMTP_mtpdevice_t *device,int const sortby)
   2957 {
   2958   LIBMTP_devicestorage_t *oldhead, *ptr1, *ptr2, *newlist;
   2959 
   2960   if (device->storage == NULL)
   2961     return -1;
   2962   if (sortby == LIBMTP_STORAGE_SORTBY_NOTSORTED)
   2963     return 0;
   2964 
   2965   oldhead = ptr1 = ptr2 = device->storage;
   2966 
   2967   newlist = NULL;
   2968 
   2969   while(oldhead != NULL) {
   2970     ptr1 = ptr2 = oldhead;
   2971     while(ptr1 != NULL) {
   2972 
   2973       if (sortby == LIBMTP_STORAGE_SORTBY_FREESPACE && ptr1->FreeSpaceInBytes > ptr2->FreeSpaceInBytes)
   2974         ptr2 = ptr1;
   2975       if (sortby == LIBMTP_STORAGE_SORTBY_MAXSPACE && ptr1->FreeSpaceInBytes > ptr2->FreeSpaceInBytes)
   2976         ptr2 = ptr1;
   2977 
   2978       ptr1 = ptr1->next;
   2979     }
   2980 
   2981     // Make our previous entries next point to our next
   2982     if(ptr2->prev != NULL) {
   2983       ptr1 = ptr2->prev;
   2984       ptr1->next = ptr2->next;
   2985     } else {
   2986       oldhead = ptr2->next;
   2987       if(oldhead != NULL)
   2988         oldhead->prev = NULL;
   2989     }
   2990 
   2991     // Make our next entries previous point to our previous
   2992     ptr1 = ptr2->next;
   2993     if(ptr1 != NULL) {
   2994       ptr1->prev = ptr2->prev;
   2995     } else {
   2996       ptr1 = ptr2->prev;
   2997       if(ptr1 != NULL)
   2998         ptr1->next = NULL;
   2999     }
   3000 
   3001     if(newlist == NULL) {
   3002       newlist = ptr2;
   3003       newlist->prev = NULL;
   3004     } else {
   3005       ptr2->prev = newlist;
   3006       newlist->next = ptr2;
   3007       newlist = newlist->next;
   3008     }
   3009   }
   3010 
   3011   if (newlist != NULL) {
   3012     newlist->next = NULL;
   3013     while(newlist->prev != NULL)
   3014       newlist = newlist->prev;
   3015     device->storage = newlist;
   3016   }
   3017 
   3018   return 0;
   3019 }
   3020 
   3021 /**
   3022  * This function grabs the first writeable storageid from the
   3023  * device storage list.
   3024  * @param device a pointer to the MTP device to locate writeable
   3025  *        storage for.
   3026  * @param fitsize a file of this file must fit on the device.
   3027  */
   3028 static uint32_t get_writeable_storageid(LIBMTP_mtpdevice_t *device,
   3029 					uint64_t fitsize)
   3030 {
   3031   LIBMTP_devicestorage_t *storage;
   3032   uint32_t store = 0x00000000; //Should this be 0xffffffffu instead?
   3033   int subcall_ret;
   3034 
   3035   // See if there is some storage we can fit this file on.
   3036   storage = device->storage;
   3037   if (storage == NULL) {
   3038     // Sometimes the storage just cannot be detected.
   3039     store = 0x00000000U;
   3040   } else {
   3041     while(storage != NULL) {
   3042       // These storages cannot be used.
   3043       if (storage->StorageType == PTP_ST_FixedROM ||
   3044 	  storage->StorageType == PTP_ST_RemovableROM) {
   3045 	storage = storage->next;
   3046 	continue;
   3047       }
   3048       // Storage IDs with the lower 16 bits 0x0000 are not supposed
   3049       // to be writeable.
   3050       if ((storage->id & 0x0000FFFFU) == 0x00000000U) {
   3051 	storage = storage->next;
   3052 	continue;
   3053       }
   3054       // Also check the access capability to avoid e.g. deletable only storages
   3055       if (storage->AccessCapability == PTP_AC_ReadOnly ||
   3056 	  storage->AccessCapability == PTP_AC_ReadOnly_with_Object_Deletion) {
   3057 	storage = storage->next;
   3058 	continue;
   3059       }
   3060       // Then see if we can fit the file.
   3061       subcall_ret = check_if_file_fits(device, storage, fitsize);
   3062       if (subcall_ret != 0) {
   3063 	storage = storage->next;
   3064       } else {
   3065 	// We found a storage that is writable and can fit the file!
   3066 	break;
   3067       }
   3068     }
   3069     if (storage == NULL) {
   3070       add_error_to_errorstack(device, LIBMTP_ERROR_STORAGE_FULL,
   3071 			      "get_writeable_storageid(): "
   3072 			      "all device storage is full or corrupt.");
   3073       return -1;
   3074     }
   3075     store = storage->id;
   3076   }
   3077 
   3078   return store;
   3079 }
   3080 
   3081 /**
   3082  * Tries to suggest a storage_id of a given ID when we have a parent
   3083  * @param device a pointer to the device where to search for the storage ID
   3084  * @param fitsize a file of this file must fit on the device.
   3085  * @param parent_id look for this ID
   3086  * @ret storageID
   3087  */
   3088 static int get_suggested_storage_id(LIBMTP_mtpdevice_t *device,
   3089 				    uint64_t fitsize,
   3090 				    uint32_t parent_id)
   3091 {
   3092   PTPParams *params = (PTPParams *) device->params;
   3093   PTPObject *ob;
   3094   uint16_t ret;
   3095 
   3096   ret = ptp_object_want(params, parent_id, PTPOBJECT_MTPPROPLIST_LOADED, &ob);
   3097   if ((ret != PTP_RC_OK) || (ob->oi.StorageID == 0)) {
   3098     add_ptp_error_to_errorstack(device, ret, "get_suggested_storage_id(): "
   3099 				"could not get storage id from parent id.");
   3100     return get_writeable_storageid(device, fitsize);
   3101   } else {
   3102     /* OK we know the parent storage, then use that */
   3103     return ob->oi.StorageID;
   3104   }
   3105 }
   3106 
   3107 /**
   3108  * This function grabs the freespace from a certain storage in
   3109  * device storage list.
   3110  * @param device a pointer to the MTP device to free the storage
   3111  * list for.
   3112  * @param storageid the storage ID for the storage to flush and
   3113  * get free space for.
   3114  * @param freespace the free space on this storage will be returned
   3115  * in this variable.
   3116  */
   3117 static int get_storage_freespace(LIBMTP_mtpdevice_t *device,
   3118 				 LIBMTP_devicestorage_t *storage,
   3119 				 uint64_t *freespace)
   3120 {
   3121   PTPParams *params = (PTPParams *) device->params;
   3122 
   3123   // Always query the device about this, since some models explicitly
   3124   // needs that. We flush all data on queries storage here.
   3125   if (ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
   3126     PTPStorageInfo storageInfo;
   3127     uint16_t ret;
   3128 
   3129     ret = ptp_getstorageinfo(params, storage->id, &storageInfo);
   3130     if (ret != PTP_RC_OK) {
   3131       add_ptp_error_to_errorstack(device, ret,
   3132 		"get_storage_freespace(): could not get storage info.");
   3133       return -1;
   3134     }
   3135     if (storage->StorageDescription != NULL) {
   3136       free(storage->StorageDescription);
   3137     }
   3138     if (storage->VolumeIdentifier != NULL) {
   3139       free(storage->VolumeIdentifier);
   3140     }
   3141     storage->StorageType = storageInfo.StorageType;
   3142     storage->FilesystemType = storageInfo.FilesystemType;
   3143     storage->AccessCapability = storageInfo.AccessCapability;
   3144     storage->MaxCapacity = storageInfo.MaxCapability;
   3145     storage->FreeSpaceInBytes = storageInfo.FreeSpaceInBytes;
   3146     storage->FreeSpaceInObjects = storageInfo.FreeSpaceInImages;
   3147     storage->StorageDescription = storageInfo.StorageDescription;
   3148     storage->VolumeIdentifier = storageInfo.VolumeLabel;
   3149   }
   3150   if(storage->FreeSpaceInBytes == (uint64_t) -1)
   3151     return -1;
   3152   *freespace = storage->FreeSpaceInBytes;
   3153   return 0;
   3154 }
   3155 
   3156 /**
   3157  * This function dumps out a large chunk of textual information
   3158  * provided from the PTP protocol and additionally some extra
   3159  * MTP-specific information where applicable.
   3160  * @param device a pointer to the MTP device to report info from.
   3161  */
   3162 void LIBMTP_Dump_Device_Info(LIBMTP_mtpdevice_t *device)
   3163 {
   3164   int i;
   3165   PTPParams *params = (PTPParams *) device->params;
   3166   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   3167   LIBMTP_devicestorage_t *storage = device->storage;
   3168   LIBMTP_device_extension_t *tmpext = device->extensions;
   3169 
   3170   printf("USB low-level info:\n");
   3171   dump_usbinfo(ptp_usb);
   3172   /* Print out some verbose information */
   3173   printf("Device info:\n");
   3174   printf("   Manufacturer: %s\n", params->deviceinfo.Manufacturer);
   3175   printf("   Model: %s\n", params->deviceinfo.Model);
   3176   printf("   Device version: %s\n", params->deviceinfo.DeviceVersion);
   3177   printf("   Serial number: %s\n", params->deviceinfo.SerialNumber);
   3178   printf("   Vendor extension ID: 0x%08x\n",
   3179 	 params->deviceinfo.VendorExtensionID);
   3180   printf("   Vendor extension description: %s\n",
   3181 	 params->deviceinfo.VendorExtensionDesc);
   3182   printf("   Detected object size: %d bits\n",
   3183 	 device->object_bitsize);
   3184   printf("   Extensions:\n");
   3185   while (tmpext != NULL) {
   3186     printf("        %s: %d.%d\n",
   3187            tmpext->name,
   3188            tmpext->major,
   3189            tmpext->minor);
   3190     tmpext = tmpext->next;
   3191   }
   3192   printf("Supported operations:\n");
   3193   for (i=0;i<params->deviceinfo.OperationsSupported_len;i++)
   3194     printf("   %04x: %s\n", params->deviceinfo.OperationsSupported[i], ptp_get_opcode_name(params, params->deviceinfo.OperationsSupported[i]));
   3195   printf("Events supported:\n");
   3196   if (params->deviceinfo.EventsSupported_len == 0) {
   3197     printf("   None.\n");
   3198   } else {
   3199     for (i=0;i<params->deviceinfo.EventsSupported_len;i++) {
   3200       printf("   0x%04x (%s)\n", params->deviceinfo.EventsSupported[i], ptp_strerror(params->deviceinfo.EventsSupported[i], params->deviceinfo.VendorExtensionID));
   3201     }
   3202   }
   3203   printf("Device Properties Supported:\n");
   3204   for (i=0;i<params->deviceinfo.DevicePropertiesSupported_len;i++) {
   3205     char const *propdesc = ptp_get_property_description(params,
   3206 			params->deviceinfo.DevicePropertiesSupported[i]);
   3207 
   3208     if (propdesc != NULL) {
   3209       printf("   0x%04x: %s\n",
   3210 	     params->deviceinfo.DevicePropertiesSupported[i], propdesc);
   3211     } else {
   3212       uint16_t prop = params->deviceinfo.DevicePropertiesSupported[i];
   3213       printf("   0x%04x: Unknown property\n", prop);
   3214     }
   3215   }
   3216 
   3217   if (ptp_operation_issupported(params,PTP_OC_MTP_GetObjectPropsSupported)) {
   3218     printf("Playable File (Object) Types and Object Properties Supported:\n");
   3219     for (i=0;i<params->deviceinfo.ImageFormats_len;i++) {
   3220       char txt[256];
   3221       uint16_t ret;
   3222       uint16_t *props = NULL;
   3223       uint32_t propcnt = 0;
   3224       int j;
   3225 
   3226       (void) ptp_render_ofc (params, params->deviceinfo.ImageFormats[i],
   3227 			     sizeof(txt), txt);
   3228       printf("   %04x: %s\n", params->deviceinfo.ImageFormats[i], txt);
   3229 
   3230       ret = ptp_mtp_getobjectpropssupported (params,
   3231 			params->deviceinfo.ImageFormats[i], &propcnt, &props);
   3232       if (ret != PTP_RC_OK) {
   3233 	add_ptp_error_to_errorstack(device, ret, "LIBMTP_Dump_Device_Info(): "
   3234 				    "error on query for object properties.");
   3235       } else {
   3236 	for (j=0;j<propcnt;j++) {
   3237 	  PTPObjectPropDesc opd;
   3238 	  int k;
   3239 
   3240 	  printf("      %04x: %s", props[j],
   3241 		 LIBMTP_Get_Property_Description(map_ptp_property_to_libmtp_property(props[j])));
   3242 	  // Get a more verbose description
   3243 	  ret = ptp_mtp_getobjectpropdesc(params, props[j],
   3244 					  params->deviceinfo.ImageFormats[i],
   3245 					  &opd);
   3246 	  if (ret != PTP_RC_OK) {
   3247 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   3248 				    "LIBMTP_Dump_Device_Info(): "
   3249 				    "could not get property description.");
   3250 	    break;
   3251 	  }
   3252 
   3253 	  if (opd.DataType == PTP_DTC_STR) {
   3254 	    printf(" STRING data type");
   3255 	    switch (opd.FormFlag) {
   3256 	    case PTP_OPFF_DateTime:
   3257 	      printf(" DATETIME FORM");
   3258 	      break;
   3259 	    case PTP_OPFF_RegularExpression:
   3260 	      printf(" REGULAR EXPRESSION FORM");
   3261 	      break;
   3262 	    case PTP_OPFF_LongString:
   3263 	      printf(" LONG STRING FORM");
   3264 	      break;
   3265 	    default:
   3266 	      break;
   3267 	    }
   3268 	  } else {
   3269 	    if (opd.DataType & PTP_DTC_ARRAY_MASK) {
   3270 	      printf(" array of");
   3271 	    }
   3272 
   3273 	    switch (opd.DataType & (~PTP_DTC_ARRAY_MASK)) {
   3274 
   3275 	    case PTP_DTC_UNDEF:
   3276 	      printf(" UNDEFINED data type");
   3277 	      break;
   3278 	    case PTP_DTC_INT8:
   3279 	      printf(" INT8 data type");
   3280 	      switch (opd.FormFlag) {
   3281 	      case PTP_OPFF_Range:
   3282 		printf(" range: MIN %d, MAX %d, STEP %d",
   3283 		       opd.FORM.Range.MinimumValue.i8,
   3284 		       opd.FORM.Range.MaximumValue.i8,
   3285 		       opd.FORM.Range.StepSize.i8);
   3286 		break;
   3287 	      case PTP_OPFF_Enumeration:
   3288 		printf(" enumeration: ");
   3289 		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
   3290 		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].i8);
   3291 		}
   3292 		break;
   3293 	      case PTP_OPFF_ByteArray:
   3294 		printf(" byte array: ");
   3295 		break;
   3296 	      default:
   3297 		printf(" ANY 8BIT VALUE form");
   3298 		break;
   3299 	      }
   3300 	      break;
   3301 
   3302 	    case PTP_DTC_UINT8:
   3303 	      printf(" UINT8 data type");
   3304 	      switch (opd.FormFlag) {
   3305 	      case PTP_OPFF_Range:
   3306 		printf(" range: MIN %d, MAX %d, STEP %d",
   3307 		       opd.FORM.Range.MinimumValue.u8,
   3308 		       opd.FORM.Range.MaximumValue.u8,
   3309 		       opd.FORM.Range.StepSize.u8);
   3310 		break;
   3311 	      case PTP_OPFF_Enumeration:
   3312 		printf(" enumeration: ");
   3313 		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
   3314 		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].u8);
   3315 		}
   3316 		break;
   3317 	      case PTP_OPFF_ByteArray:
   3318 		printf(" byte array: ");
   3319 		break;
   3320 	      default:
   3321 		printf(" ANY 8BIT VALUE form");
   3322 		break;
   3323 	      }
   3324 	      break;
   3325 
   3326 	    case PTP_DTC_INT16:
   3327 	      printf(" INT16 data type");
   3328 	      switch (opd.FormFlag) {
   3329 	      case PTP_OPFF_Range:
   3330 	      printf(" range: MIN %d, MAX %d, STEP %d",
   3331 		     opd.FORM.Range.MinimumValue.i16,
   3332 		     opd.FORM.Range.MaximumValue.i16,
   3333 		     opd.FORM.Range.StepSize.i16);
   3334 	      break;
   3335 	      case PTP_OPFF_Enumeration:
   3336 		printf(" enumeration: ");
   3337 		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
   3338 		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].i16);
   3339 		}
   3340 		break;
   3341 	      default:
   3342 		printf(" ANY 16BIT VALUE form");
   3343 		break;
   3344 	      }
   3345 	      break;
   3346 
   3347 	    case PTP_DTC_UINT16:
   3348 	      printf(" UINT16 data type");
   3349 	      switch (opd.FormFlag) {
   3350 	      case PTP_OPFF_Range:
   3351 		printf(" range: MIN %d, MAX %d, STEP %d",
   3352 		       opd.FORM.Range.MinimumValue.u16,
   3353 		       opd.FORM.Range.MaximumValue.u16,
   3354 		       opd.FORM.Range.StepSize.u16);
   3355 		break;
   3356 	      case PTP_OPFF_Enumeration:
   3357 		printf(" enumeration: ");
   3358 		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
   3359 		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].u16);
   3360 		}
   3361 		break;
   3362 	      default:
   3363 		printf(" ANY 16BIT VALUE form");
   3364 		break;
   3365 	      }
   3366 	      break;
   3367 
   3368 	    case PTP_DTC_INT32:
   3369 	      printf(" INT32 data type");
   3370 	      switch (opd.FormFlag) {
   3371 	      case PTP_OPFF_Range:
   3372 		printf(" range: MIN %d, MAX %d, STEP %d",
   3373 		       opd.FORM.Range.MinimumValue.i32,
   3374 		       opd.FORM.Range.MaximumValue.i32,
   3375 		       opd.FORM.Range.StepSize.i32);
   3376 		break;
   3377 	      case PTP_OPFF_Enumeration:
   3378 		printf(" enumeration: ");
   3379 		for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
   3380 		  printf("%d, ", opd.FORM.Enum.SupportedValue[k].i32);
   3381 		}
   3382 		break;
   3383 	      default:
   3384 		printf(" ANY 32BIT VALUE form");
   3385 		break;
   3386 	      }
   3387 	      break;
   3388 
   3389 	    case PTP_DTC_UINT32:
   3390 	      printf(" UINT32 data type");
   3391 	      switch (opd.FormFlag) {
   3392 	      case PTP_OPFF_Range:
   3393 		printf(" range: MIN %d, MAX %d, STEP %d",
   3394 		       opd.FORM.Range.MinimumValue.u32,
   3395 		       opd.FORM.Range.MaximumValue.u32,
   3396 		       opd.FORM.Range.StepSize.u32);
   3397 		break;
   3398 	      case PTP_OPFF_Enumeration:
   3399 		// Special pretty-print for FOURCC codes
   3400 		if (params->deviceinfo.ImageFormats[i] == PTP_OPC_VideoFourCCCodec) {
   3401 		  printf(" enumeration of u32 casted FOURCC: ");
   3402 		  for (k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
   3403 		    if (opd.FORM.Enum.SupportedValue[k].u32 == 0) {
   3404 		      printf("ANY, ");
   3405 		    } else {
   3406 		      char fourcc[6];
   3407 		      fourcc[0] = (opd.FORM.Enum.SupportedValue[k].u32 >> 24) & 0xFFU;
   3408 		      fourcc[1] = (opd.FORM.Enum.SupportedValue[k].u32 >> 16) & 0xFFU;
   3409 		      fourcc[2] = (opd.FORM.Enum.SupportedValue[k].u32 >> 8) & 0xFFU;
   3410 		      fourcc[3] = opd.FORM.Enum.SupportedValue[k].u32 & 0xFFU;
   3411 		      fourcc[4] = '\n';
   3412 		      fourcc[5] = '\0';
   3413 		      printf("\"%s\", ", fourcc);
   3414 		    }
   3415 		  }
   3416 		} else {
   3417 		  printf(" enumeration: ");
   3418 		  for(k=0;k<opd.FORM.Enum.NumberOfValues;k++) {
   3419 		    printf("%d, ", opd.FORM.Enum.SupportedValue[k].u32);
   3420 		  }
   3421 		}
   3422 		break;
   3423 	      default:
   3424 		printf(" ANY 32BIT VALUE form");
   3425 		break;
   3426 	      }
   3427 	      break;
   3428 
   3429 	    case PTP_DTC_INT64:
   3430 	      printf(" INT64 data type");
   3431 	      break;
   3432 
   3433 	    case PTP_DTC_UINT64:
   3434 	      printf(" UINT64 data type");
   3435 	      break;
   3436 
   3437 	    case PTP_DTC_INT128:
   3438 	      printf(" INT128 data type");
   3439 	      break;
   3440 
   3441 	    case PTP_DTC_UINT128:
   3442 	      printf(" UINT128 data type");
   3443 	      break;
   3444 
   3445 	    default:
   3446 	      printf(" UNKNOWN data type");
   3447 	      break;
   3448 	    }
   3449 	  }
   3450 	  if (opd.GetSet) {
   3451 	    printf(" GET/SET");
   3452 	  } else {
   3453 	    printf(" READ ONLY");
   3454 	  }
   3455 	  printf("\n");
   3456 	  ptp_free_objectpropdesc(&opd);
   3457 	}
   3458 	free(props);
   3459       }
   3460     }
   3461   }
   3462 
   3463   if(storage != NULL &&
   3464      ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
   3465     printf("Storage Devices:\n");
   3466     while(storage != NULL) {
   3467       printf("   StorageID: 0x%08x\n",storage->id);
   3468       printf("      StorageType: 0x%04x ",storage->StorageType);
   3469       switch (storage->StorageType) {
   3470       case PTP_ST_Undefined:
   3471 	printf("(undefined)\n");
   3472 	break;
   3473       case PTP_ST_FixedROM:
   3474 	printf("fixed ROM storage\n");
   3475 	break;
   3476       case PTP_ST_RemovableROM:
   3477 	printf("removable ROM storage\n");
   3478 	break;
   3479       case PTP_ST_FixedRAM:
   3480 	printf("fixed RAM storage\n");
   3481 	break;
   3482       case PTP_ST_RemovableRAM:
   3483 	printf("removable RAM storage\n");
   3484 	break;
   3485       default:
   3486 	printf("UNKNOWN storage\n");
   3487 	break;
   3488       }
   3489       printf("      FilesystemType: 0x%04x ",storage->FilesystemType);
   3490       switch(storage->FilesystemType) {
   3491       case PTP_FST_Undefined:
   3492 	printf("(undefined)\n");
   3493 	break;
   3494       case PTP_FST_GenericFlat:
   3495 	printf("generic flat filesystem\n");
   3496 	break;
   3497       case PTP_FST_GenericHierarchical:
   3498 	printf("generic hierarchical\n");
   3499 	break;
   3500       case PTP_FST_DCF:
   3501 	printf("DCF\n");
   3502 	break;
   3503       default:
   3504 	printf("UNKNONWN filesystem type\n");
   3505 	break;
   3506       }
   3507       printf("      AccessCapability: 0x%04x ",storage->AccessCapability);
   3508       switch(storage->AccessCapability) {
   3509       case PTP_AC_ReadWrite:
   3510 	printf("read/write\n");
   3511 	break;
   3512       case PTP_AC_ReadOnly:
   3513 	printf("read only\n");
   3514 	break;
   3515       case PTP_AC_ReadOnly_with_Object_Deletion:
   3516 	printf("read only + object deletion\n");
   3517 	break;
   3518       default:
   3519 	printf("UNKNOWN access capability\n");
   3520 	break;
   3521       }
   3522       printf("      MaxCapacity: %llu\n",
   3523 	     (long long unsigned int) storage->MaxCapacity);
   3524       printf("      FreeSpaceInBytes: %llu\n",
   3525 	     (long long unsigned int) storage->FreeSpaceInBytes);
   3526       printf("      FreeSpaceInObjects: %llu\n",
   3527 	     (long long unsigned int) storage->FreeSpaceInObjects);
   3528       printf("      StorageDescription: %s\n",storage->StorageDescription);
   3529       printf("      VolumeIdentifier: %s\n",storage->VolumeIdentifier);
   3530       storage = storage->next;
   3531     }
   3532   }
   3533 
   3534   printf("Special directories:\n");
   3535   printf("   Default music folder: 0x%08x\n",
   3536 	 device->default_music_folder);
   3537   printf("   Default playlist folder: 0x%08x\n",
   3538 	 device->default_playlist_folder);
   3539   printf("   Default picture folder: 0x%08x\n",
   3540 	 device->default_picture_folder);
   3541   printf("   Default video folder: 0x%08x\n",
   3542 	 device->default_video_folder);
   3543   printf("   Default organizer folder: 0x%08x\n",
   3544 	 device->default_organizer_folder);
   3545   printf("   Default zencast folder: 0x%08x\n",
   3546 	 device->default_zencast_folder);
   3547   printf("   Default album folder: 0x%08x\n",
   3548 	 device->default_album_folder);
   3549   printf("   Default text folder: 0x%08x\n",
   3550 	 device->default_text_folder);
   3551 }
   3552 
   3553 /**
   3554  * This resets a device in case it supports the <code>PTP_OC_ResetDevice</code>
   3555  * operation code (0x1010).
   3556  * @param device a pointer to the device to reset.
   3557  * @return 0 on success, any other value means failure.
   3558  */
   3559 int LIBMTP_Reset_Device(LIBMTP_mtpdevice_t *device)
   3560 {
   3561   PTPParams *params = (PTPParams *) device->params;
   3562   uint16_t ret;
   3563 
   3564   if (!ptp_operation_issupported(params,PTP_OC_ResetDevice)) {
   3565     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   3566 			    "LIBMTP_Reset_Device(): "
   3567 			    "device does not support resetting.");
   3568     return -1;
   3569   }
   3570   ret = ptp_resetdevice(params);
   3571   if (ret != PTP_RC_OK) {
   3572     add_ptp_error_to_errorstack(device, ret, "Error resetting.");
   3573     return -1;
   3574   }
   3575   return 0;
   3576 }
   3577 
   3578 /**
   3579  * This retrieves the manufacturer name of an MTP device.
   3580  * @param device a pointer to the device to get the manufacturer name for.
   3581  * @return a newly allocated UTF-8 string representing the manufacturer name.
   3582  *         The string must be freed by the caller after use. If the call
   3583  *         was unsuccessful this will contain NULL.
   3584  */
   3585 char *LIBMTP_Get_Manufacturername(LIBMTP_mtpdevice_t *device)
   3586 {
   3587   char *retmanuf = NULL;
   3588   PTPParams *params = (PTPParams *) device->params;
   3589 
   3590   if (params->deviceinfo.Manufacturer != NULL) {
   3591     retmanuf = strdup(params->deviceinfo.Manufacturer);
   3592   }
   3593   return retmanuf;
   3594 }
   3595 
   3596 /**
   3597  * This retrieves the model name (often equal to product name)
   3598  * of an MTP device.
   3599  * @param device a pointer to the device to get the model name for.
   3600  * @return a newly allocated UTF-8 string representing the model name.
   3601  *         The string must be freed by the caller after use. If the call
   3602  *         was unsuccessful this will contain NULL.
   3603  */
   3604 char *LIBMTP_Get_Modelname(LIBMTP_mtpdevice_t *device)
   3605 {
   3606   char *retmodel = NULL;
   3607   PTPParams *params = (PTPParams *) device->params;
   3608 
   3609   if (params->deviceinfo.Model != NULL) {
   3610     retmodel = strdup(params->deviceinfo.Model);
   3611   }
   3612   return retmodel;
   3613 }
   3614 
   3615 /**
   3616  * This retrieves the serial number of an MTP device.
   3617  * @param device a pointer to the device to get the serial number for.
   3618  * @return a newly allocated UTF-8 string representing the serial number.
   3619  *         The string must be freed by the caller after use. If the call
   3620  *         was unsuccessful this will contain NULL.
   3621  */
   3622 char *LIBMTP_Get_Serialnumber(LIBMTP_mtpdevice_t *device)
   3623 {
   3624   char *retnumber = NULL;
   3625   PTPParams *params = (PTPParams *) device->params;
   3626 
   3627   if (params->deviceinfo.SerialNumber != NULL) {
   3628     retnumber = strdup(params->deviceinfo.SerialNumber);
   3629   }
   3630   return retnumber;
   3631 }
   3632 
   3633 /**
   3634  * This retrieves the device version (hardware and firmware version) of an
   3635  * MTP device.
   3636  * @param device a pointer to the device to get the device version for.
   3637  * @return a newly allocated UTF-8 string representing the device version.
   3638  *         The string must be freed by the caller after use. If the call
   3639  *         was unsuccessful this will contain NULL.
   3640  */
   3641 char *LIBMTP_Get_Deviceversion(LIBMTP_mtpdevice_t *device)
   3642 {
   3643   char *retversion = NULL;
   3644   PTPParams *params = (PTPParams *) device->params;
   3645 
   3646   if (params->deviceinfo.DeviceVersion != NULL) {
   3647     retversion = strdup(params->deviceinfo.DeviceVersion);
   3648   }
   3649   return retversion;
   3650 }
   3651 
   3652 
   3653 /**
   3654  * This retrieves the "friendly name" of an MTP device. Usually
   3655  * this is simply the name of the owner or something like
   3656  * "John Doe's Digital Audio Player". This property should be supported
   3657  * by all MTP devices.
   3658  * @param device a pointer to the device to get the friendly name for.
   3659  * @return a newly allocated UTF-8 string representing the friendly name.
   3660  *         The string must be freed by the caller after use.
   3661  * @see LIBMTP_Set_Friendlyname()
   3662  */
   3663 char *LIBMTP_Get_Friendlyname(LIBMTP_mtpdevice_t *device)
   3664 {
   3665   PTPPropertyValue propval;
   3666   char *retstring = NULL;
   3667   PTPParams *params = (PTPParams *) device->params;
   3668   uint16_t ret;
   3669 
   3670   if (!ptp_property_issupported(params, PTP_DPC_MTP_DeviceFriendlyName)) {
   3671     return NULL;
   3672   }
   3673 
   3674   ret = ptp_getdevicepropvalue(params,
   3675 			       PTP_DPC_MTP_DeviceFriendlyName,
   3676 			       &propval,
   3677 			       PTP_DTC_STR);
   3678   if (ret != PTP_RC_OK) {
   3679     add_ptp_error_to_errorstack(device, ret, "Error getting friendlyname.");
   3680     return NULL;
   3681   }
   3682   if (propval.str != NULL) {
   3683     retstring = strdup(propval.str);
   3684     free(propval.str);
   3685   }
   3686   return retstring;
   3687 }
   3688 
   3689 /**
   3690  * Sets the "friendly name" of an MTP device.
   3691  * @param device a pointer to the device to set the friendly name for.
   3692  * @param friendlyname the new friendly name for the device.
   3693  * @return 0 on success, any other value means failure.
   3694  * @see LIBMTP_Get_Friendlyname()
   3695  */
   3696 int LIBMTP_Set_Friendlyname(LIBMTP_mtpdevice_t *device,
   3697 			 char const * const friendlyname)
   3698 {
   3699   PTPPropertyValue propval;
   3700   PTPParams *params = (PTPParams *) device->params;
   3701   uint16_t ret;
   3702 
   3703   if (!ptp_property_issupported(params, PTP_DPC_MTP_DeviceFriendlyName)) {
   3704     return -1;
   3705   }
   3706   propval.str = (char *) friendlyname;
   3707   ret = ptp_setdevicepropvalue(params,
   3708 			       PTP_DPC_MTP_DeviceFriendlyName,
   3709 			       &propval,
   3710 			       PTP_DTC_STR);
   3711   if (ret != PTP_RC_OK) {
   3712     add_ptp_error_to_errorstack(device, ret, "Error setting friendlyname.");
   3713     return -1;
   3714   }
   3715   return 0;
   3716 }
   3717 
   3718 /**
   3719  * This retrieves the syncronization partner of an MTP device. This
   3720  * property should be supported by all MTP devices.
   3721  * @param device a pointer to the device to get the sync partner for.
   3722  * @return a newly allocated UTF-8 string representing the synchronization
   3723  *         partner. The string must be freed by the caller after use.
   3724  * @see LIBMTP_Set_Syncpartner()
   3725  */
   3726 char *LIBMTP_Get_Syncpartner(LIBMTP_mtpdevice_t *device)
   3727 {
   3728   PTPPropertyValue propval;
   3729   char *retstring = NULL;
   3730   PTPParams *params = (PTPParams *) device->params;
   3731   uint16_t ret;
   3732 
   3733   if (!ptp_property_issupported(params, PTP_DPC_MTP_SynchronizationPartner)) {
   3734     return NULL;
   3735   }
   3736 
   3737   ret = ptp_getdevicepropvalue(params,
   3738 			       PTP_DPC_MTP_SynchronizationPartner,
   3739 			       &propval,
   3740 			       PTP_DTC_STR);
   3741   if (ret != PTP_RC_OK) {
   3742     add_ptp_error_to_errorstack(device, ret, "Error getting syncpartner.");
   3743     return NULL;
   3744   }
   3745   if (propval.str != NULL) {
   3746     retstring = strdup(propval.str);
   3747     free(propval.str);
   3748   }
   3749   return retstring;
   3750 }
   3751 
   3752 
   3753 /**
   3754  * Sets the synchronization partner of an MTP device. Note that
   3755  * we have no idea what the effect of setting this to "foobar"
   3756  * may be. But the general idea seems to be to tell which program
   3757  * shall synchronize with this device and tell others to leave
   3758  * it alone.
   3759  * @param device a pointer to the device to set the sync partner for.
   3760  * @param syncpartner the new synchronization partner for the device.
   3761  * @return 0 on success, any other value means failure.
   3762  * @see LIBMTP_Get_Syncpartner()
   3763  */
   3764 int LIBMTP_Set_Syncpartner(LIBMTP_mtpdevice_t *device,
   3765 			 char const * const syncpartner)
   3766 {
   3767   PTPPropertyValue propval;
   3768   PTPParams *params = (PTPParams *) device->params;
   3769   uint16_t ret;
   3770 
   3771   if (!ptp_property_issupported(params, PTP_DPC_MTP_SynchronizationPartner)) {
   3772     return -1;
   3773   }
   3774   propval.str = (char *) syncpartner;
   3775   ret = ptp_setdevicepropvalue(params,
   3776 			       PTP_DPC_MTP_SynchronizationPartner,
   3777 			       &propval,
   3778 			       PTP_DTC_STR);
   3779   if (ret != PTP_RC_OK) {
   3780     add_ptp_error_to_errorstack(device, ret, "Error setting syncpartner.");
   3781     return -1;
   3782   }
   3783   return 0;
   3784 }
   3785 
   3786 /**
   3787  * Checks if the device can stora a file of this size or
   3788  * if it's too big.
   3789  * @param device a pointer to the device.
   3790  * @param filesize the size of the file to check whether it will fit.
   3791  * @param storageid the ID of the storage to try to fit the file on.
   3792  * @return 0 if the file fits, any other value means failure.
   3793  */
   3794 static int check_if_file_fits(LIBMTP_mtpdevice_t *device,
   3795 			      LIBMTP_devicestorage_t *storage,
   3796 			      uint64_t const filesize) {
   3797   PTPParams *params = (PTPParams *) device->params;
   3798   uint64_t freebytes;
   3799   int ret;
   3800 
   3801   // If we cannot check the storage, no big deal.
   3802   if (!ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
   3803     return 0;
   3804   }
   3805 
   3806   ret = get_storage_freespace(device, storage, &freebytes);
   3807   if (ret != 0) {
   3808     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   3809 			    "check_if_file_fits(): error checking free storage.");
   3810     return -1;
   3811   } else {
   3812     // See if it fits.
   3813     if (filesize > freebytes) {
   3814       return -1;
   3815     }
   3816   }
   3817   return 0;
   3818 }
   3819 
   3820 
   3821 /**
   3822  * This function retrieves the current battery level on the device.
   3823  * @param device a pointer to the device to get the battery level for.
   3824  * @param maximum_level a pointer to a variable that will hold the
   3825  *        maximum level of the battery if the call was successful.
   3826  * @param current_level a pointer to a variable that will hold the
   3827  *        current level of the battery if the call was successful.
   3828  *        A value of 0 means that the device is on external power.
   3829  * @return 0 if the storage info was successfully retrieved, any other
   3830  *        means failure. A typical cause of failure is that
   3831  *        the device does not support the battery level property.
   3832  */
   3833 int LIBMTP_Get_Batterylevel(LIBMTP_mtpdevice_t *device,
   3834 			    uint8_t * const maximum_level,
   3835 			    uint8_t * const current_level)
   3836 {
   3837   PTPPropertyValue propval;
   3838   uint16_t ret;
   3839   PTPParams *params = (PTPParams *) device->params;
   3840   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   3841 
   3842   *maximum_level = 0;
   3843   *current_level = 0;
   3844 
   3845   if (FLAG_BROKEN_BATTERY_LEVEL(ptp_usb) ||
   3846       !ptp_property_issupported(params, PTP_DPC_BatteryLevel)) {
   3847     return -1;
   3848   }
   3849 
   3850   ret = ptp_getdevicepropvalue(params, PTP_DPC_BatteryLevel,
   3851 			       &propval, PTP_DTC_UINT8);
   3852   if (ret != PTP_RC_OK) {
   3853     add_ptp_error_to_errorstack(device, ret,
   3854 				"LIBMTP_Get_Batterylevel(): "
   3855 				"could not get device property value.");
   3856     return -1;
   3857   }
   3858 
   3859   *maximum_level = device->maximum_battery_level;
   3860   *current_level = propval.u8;
   3861 
   3862   return 0;
   3863 }
   3864 
   3865 
   3866 /**
   3867  * Formats device storage (if the device supports the operation).
   3868  * WARNING: This WILL delete all data from the device. Make sure you've
   3869  * got confirmation from the user BEFORE you call this function.
   3870  *
   3871  * @param device a pointer to the device containing the storage to format.
   3872  * @param storage the actual storage to format.
   3873  * @return 0 on success, any other value means failure.
   3874  */
   3875 int LIBMTP_Format_Storage(LIBMTP_mtpdevice_t *device,
   3876 			  LIBMTP_devicestorage_t *storage)
   3877 {
   3878   uint16_t ret;
   3879   PTPParams *params = (PTPParams *) device->params;
   3880 
   3881   if (!ptp_operation_issupported(params,PTP_OC_FormatStore)) {
   3882     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   3883 			    "LIBMTP_Format_Storage(): "
   3884 			    "device does not support formatting storage.");
   3885     return -1;
   3886   }
   3887   ret = ptp_formatstore(params, storage->id);
   3888   if (ret != PTP_RC_OK) {
   3889     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Format_Storage(): "
   3890 				"failed to format storage.");
   3891     return -1;
   3892   }
   3893   return 0;
   3894 }
   3895 
   3896 /**
   3897  * Helper function to extract a unicode property off a device.
   3898  * This is the standard way of retrieveing unicode device
   3899  * properties as described by the PTP spec.
   3900  * @param device a pointer to the device to get the property from.
   3901  * @param unicstring a pointer to a pointer that will hold the
   3902  *        property after this call is completed.
   3903  * @param property the property to retrieve.
   3904  * @return 0 on success, any other value means failure.
   3905  */
   3906 static int get_device_unicode_property(LIBMTP_mtpdevice_t *device,
   3907 				       char **unicstring, uint16_t property)
   3908 {
   3909   PTPPropertyValue propval;
   3910   PTPParams *params = (PTPParams *) device->params;
   3911   uint16_t *tmp;
   3912   uint16_t ret;
   3913   int i;
   3914 
   3915   if (!ptp_property_issupported(params, property)) {
   3916     return -1;
   3917   }
   3918 
   3919   // Unicode strings are 16bit unsigned integer arrays.
   3920   ret = ptp_getdevicepropvalue(params,
   3921 			       property,
   3922 			       &propval,
   3923 			       PTP_DTC_AUINT16);
   3924   if (ret != PTP_RC_OK) {
   3925     // TODO: add a note on WHICH property that we failed to get.
   3926     *unicstring = NULL;
   3927     add_ptp_error_to_errorstack(device, ret,
   3928 				"get_device_unicode_property(): "
   3929 				"failed to get unicode property.");
   3930     return -1;
   3931   }
   3932 
   3933   // Extract the actual array.
   3934   // printf("Array of %d elements\n", propval.a.count);
   3935   tmp = malloc((propval.a.count + 1)*sizeof(uint16_t));
   3936   for (i = 0; i < propval.a.count; i++) {
   3937     tmp[i] = propval.a.v[i].u16;
   3938     // printf("%04x ", tmp[i]);
   3939   }
   3940   tmp[propval.a.count] = 0x0000U;
   3941   free(propval.a.v);
   3942 
   3943   *unicstring = utf16_to_utf8(device, tmp);
   3944 
   3945   free(tmp);
   3946 
   3947   return 0;
   3948 }
   3949 
   3950 /**
   3951  * This function returns the secure time as an XML document string from
   3952  * the device.
   3953  * @param device a pointer to the device to get the secure time for.
   3954  * @param sectime the secure time string as an XML document or NULL if the call
   3955  *         failed or the secure time property is not supported. This string
   3956  *         must be <code>free()</code>:ed by the caller after use.
   3957  * @return 0 on success, any other value means failure.
   3958  */
   3959 int LIBMTP_Get_Secure_Time(LIBMTP_mtpdevice_t *device, char ** const sectime)
   3960 {
   3961   return get_device_unicode_property(device, sectime, PTP_DPC_MTP_SecureTime);
   3962 }
   3963 
   3964 /**
   3965  * This function returns the device (public key) certificate as an
   3966  * XML document string from the device.
   3967  * @param device a pointer to the device to get the device certificate for.
   3968  * @param devcert the device certificate as an XML string or NULL if the call
   3969  *        failed or the device certificate property is not supported. This
   3970  *        string must be <code>free()</code>:ed by the caller after use.
   3971  * @return 0 on success, any other value means failure.
   3972  */
   3973 int LIBMTP_Get_Device_Certificate(LIBMTP_mtpdevice_t *device, char ** const devcert)
   3974 {
   3975   return get_device_unicode_property(device, devcert,
   3976 				     PTP_DPC_MTP_DeviceCertificate);
   3977 }
   3978 
   3979 /**
   3980  * This function retrieves a list of supported file types, i.e. the file
   3981  * types that this device claims it supports, e.g. audio file types that
   3982  * the device can play etc. This list is mitigated to
   3983  * inlcude the file types that libmtp can handle, i.e. it will not list
   3984  * filetypes that libmtp will handle internally like playlists and folders.
   3985  * @param device a pointer to the device to get the filetype capabilities for.
   3986  * @param filetypes a pointer to a pointer that will hold the list of
   3987  *        supported filetypes if the call was successful. This list must
   3988  *        be <code>free()</code>:ed by the caller after use.
   3989  * @param length a pointer to a variable that will hold the length of the
   3990  *        list of supported filetypes if the call was successful.
   3991  * @return 0 on success, any other value means failure.
   3992  * @see LIBMTP_Get_Filetype_Description()
   3993  */
   3994 int LIBMTP_Get_Supported_Filetypes(LIBMTP_mtpdevice_t *device, uint16_t ** const filetypes,
   3995 				  uint16_t * const length)
   3996 {
   3997   PTPParams *params = (PTPParams *) device->params;
   3998   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   3999   uint16_t *localtypes;
   4000   uint16_t localtypelen;
   4001   uint32_t i;
   4002 
   4003   // This is more memory than needed if there are unknown types, but what the heck.
   4004   localtypes = (uint16_t *) malloc(params->deviceinfo.ImageFormats_len * sizeof(uint16_t));
   4005   localtypelen = 0;
   4006 
   4007   for (i=0;i<params->deviceinfo.ImageFormats_len;i++) {
   4008     uint16_t localtype = map_ptp_type_to_libmtp_type(params->deviceinfo.ImageFormats[i]);
   4009     if (localtype != LIBMTP_FILETYPE_UNKNOWN) {
   4010       localtypes[localtypelen] = localtype;
   4011       localtypelen++;
   4012     }
   4013   }
   4014   // The forgotten Ogg support on YP-10 and others...
   4015   if (FLAG_OGG_IS_UNKNOWN(ptp_usb)) {
   4016     localtypes = (uint16_t *) realloc(localtypes,
   4017 		(params->deviceinfo.ImageFormats_len+1) * sizeof(uint16_t));
   4018     localtypes[localtypelen] = LIBMTP_FILETYPE_OGG;
   4019     localtypelen++;
   4020   }
   4021   // The forgotten FLAC support on Cowon iAudio S9 and others...
   4022   if (FLAG_FLAC_IS_UNKNOWN(ptp_usb)) {
   4023     localtypes = (uint16_t *) realloc(localtypes,
   4024 		(params->deviceinfo.ImageFormats_len+1) * sizeof(uint16_t));
   4025     localtypes[localtypelen] = LIBMTP_FILETYPE_FLAC;
   4026     localtypelen++;
   4027   }
   4028 
   4029   *filetypes = localtypes;
   4030   *length = localtypelen;
   4031 
   4032   return 0;
   4033 }
   4034 
   4035 /**
   4036  * This function checks if the device has some specific capabilities, in
   4037  * order to avoid calling APIs that may disturb the device.
   4038  *
   4039  * @param device a pointer to the device to check the capability on.
   4040  * @param cap the capability to check.
   4041  * @return 0 if not supported, any other value means the device has the
   4042  * requested capability.
   4043  */
   4044 int LIBMTP_Check_Capability(LIBMTP_mtpdevice_t *device, LIBMTP_devicecap_t cap)
   4045 {
   4046   switch (cap) {
   4047   case LIBMTP_DEVICECAP_GetPartialObject:
   4048     return (ptp_operation_issupported(device->params,
   4049 				      PTP_OC_GetPartialObject) ||
   4050 	    ptp_operation_issupported(device->params,
   4051 				      PTP_OC_ANDROID_GetPartialObject64));
   4052   case LIBMTP_DEVICECAP_SendPartialObject:
   4053     return ptp_operation_issupported(device->params,
   4054 				     PTP_OC_ANDROID_SendPartialObject);
   4055   case LIBMTP_DEVICECAP_EditObjects:
   4056     return (ptp_operation_issupported(device->params,
   4057 				      PTP_OC_ANDROID_TruncateObject) &&
   4058 	    ptp_operation_issupported(device->params,
   4059 				      PTP_OC_ANDROID_BeginEditObject) &&
   4060 	    ptp_operation_issupported(device->params,
   4061 				      PTP_OC_ANDROID_EndEditObject));
   4062   /*
   4063    * Handle other capabilities here, this is also a good place to
   4064    * blacklist some advanced operations on specific devices if need
   4065    * be.
   4066    */
   4067 
   4068   default:
   4069     break;
   4070   }
   4071   return 0;
   4072 }
   4073 
   4074 /**
   4075  * This function updates all the storage id's of a device and their
   4076  * properties, then creates a linked list and puts the list head into
   4077  * the device struct. It also optionally sorts this list. If you want
   4078  * to display storage information in your application you should call
   4079  * this function, then dereference the device struct
   4080  * (<code>device-&gt;storage</code>) to get out information on the storage.
   4081  *
   4082  * You need to call this everytime you want to update the
   4083  * <code>device-&gt;storage</code> list, for example anytime you need
   4084  * to check available storage somewhere.
   4085  *
   4086  * <b>WARNING:</b> since this list is dynamically updated, do not
   4087  * reference its fields in external applications by pointer! E.g
   4088  * do not put a reference to any <code>char *</code> field. instead
   4089  * <code>strncpy()</code> it!
   4090  *
   4091  * @param device a pointer to the device to get the storage for.
   4092  * @param sortby an integer that determines the sorting of the storage list.
   4093  *        Valid sort methods are defined in libmtp.h with beginning with
   4094  *        LIBMTP_STORAGE_SORTBY_. 0 or LIBMTP_STORAGE_SORTBY_NOTSORTED to not
   4095  *        sort.
   4096  * @return 0 on success, 1 success but only with storage id's, storage
   4097  *        properities could not be retrieved and -1 means failure.
   4098  */
   4099 int LIBMTP_Get_Storage(LIBMTP_mtpdevice_t *device, int const sortby)
   4100 {
   4101   uint32_t i = 0;
   4102   PTPStorageInfo storageInfo;
   4103   PTPParams *params = (PTPParams *) device->params;
   4104   PTPStorageIDs storageIDs;
   4105   LIBMTP_devicestorage_t *storage = NULL;
   4106   LIBMTP_devicestorage_t *storageprev = NULL;
   4107 
   4108   if (device->storage != NULL)
   4109     free_storage_list(device);
   4110 
   4111   // if (!ptp_operation_issupported(params,PTP_OC_GetStorageIDs))
   4112   //   return -1;
   4113   if (ptp_getstorageids (params, &storageIDs) != PTP_RC_OK)
   4114     return -1;
   4115   if (storageIDs.n < 1)
   4116     return -1;
   4117 
   4118   if (!ptp_operation_issupported(params,PTP_OC_GetStorageInfo)) {
   4119     for (i = 0; i < storageIDs.n; i++) {
   4120 
   4121       storage = (LIBMTP_devicestorage_t *)
   4122 	malloc(sizeof(LIBMTP_devicestorage_t));
   4123       storage->prev = storageprev;
   4124       if (storageprev != NULL)
   4125         storageprev->next = storage;
   4126       if (device->storage == NULL)
   4127         device->storage = storage;
   4128 
   4129       storage->id = storageIDs.Storage[i];
   4130       storage->StorageType = PTP_ST_Undefined;
   4131       storage->FilesystemType = PTP_FST_Undefined;
   4132       storage->AccessCapability = PTP_AC_ReadWrite;
   4133       storage->MaxCapacity = (uint64_t) -1;
   4134       storage->FreeSpaceInBytes = (uint64_t) -1;
   4135       storage->FreeSpaceInObjects = (uint64_t) -1;
   4136       storage->StorageDescription = strdup("Unknown storage");
   4137       storage->VolumeIdentifier = strdup("Unknown volume");
   4138       storage->next = NULL;
   4139 
   4140       storageprev = storage;
   4141     }
   4142     free(storageIDs.Storage);
   4143     return 1;
   4144   } else {
   4145     for (i = 0; i < storageIDs.n; i++) {
   4146       uint16_t ret;
   4147       ret = ptp_getstorageinfo(params, storageIDs.Storage[i], &storageInfo);
   4148       if (ret != PTP_RC_OK) {
   4149 	add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Storage(): "
   4150 				    "Could not get storage info.");
   4151 	if (device->storage != NULL) {
   4152           free_storage_list(device);
   4153 	}
   4154 	return -1;
   4155       }
   4156 
   4157       storage = (LIBMTP_devicestorage_t *)
   4158 	malloc(sizeof(LIBMTP_devicestorage_t));
   4159       storage->prev = storageprev;
   4160       if (storageprev != NULL)
   4161         storageprev->next = storage;
   4162       if (device->storage == NULL)
   4163         device->storage = storage;
   4164 
   4165       storage->id = storageIDs.Storage[i];
   4166       storage->StorageType = storageInfo.StorageType;
   4167       storage->FilesystemType = storageInfo.FilesystemType;
   4168       storage->AccessCapability = storageInfo.AccessCapability;
   4169       storage->MaxCapacity = storageInfo.MaxCapability;
   4170       storage->FreeSpaceInBytes = storageInfo.FreeSpaceInBytes;
   4171       storage->FreeSpaceInObjects = storageInfo.FreeSpaceInImages;
   4172       storage->StorageDescription = storageInfo.StorageDescription;
   4173       storage->VolumeIdentifier = storageInfo.VolumeLabel;
   4174       storage->next = NULL;
   4175 
   4176       storageprev = storage;
   4177     }
   4178 
   4179     if (storage != NULL)
   4180       storage->next = NULL;
   4181 
   4182     sort_storage_by(device,sortby);
   4183     free(storageIDs.Storage);
   4184     return 0;
   4185   }
   4186 }
   4187 
   4188 /**
   4189  * This creates a new file metadata structure and allocates memory
   4190  * for it. Notice that if you add strings to this structure they
   4191  * will be freed by the corresponding <code>LIBMTP_destroy_file_t</code>
   4192  * operation later, so be careful of using strdup() when assigning
   4193  * strings, e.g.:
   4194  *
   4195  * <pre>
   4196  * LIBMTP_file_t *file = LIBMTP_new_file_t();
   4197  * file->filename = strdup(namestr);
   4198  * ....
   4199  * LIBMTP_destroy_file_t(file);
   4200  * </pre>
   4201  *
   4202  * @return a pointer to the newly allocated metadata structure.
   4203  * @see LIBMTP_destroy_file_t()
   4204  */
   4205 LIBMTP_file_t *LIBMTP_new_file_t(void)
   4206 {
   4207   LIBMTP_file_t *new = (LIBMTP_file_t *) malloc(sizeof(LIBMTP_file_t));
   4208   if (new == NULL) {
   4209     return NULL;
   4210   }
   4211   new->filename = NULL;
   4212   new->item_id = 0;
   4213   new->parent_id = 0;
   4214   new->storage_id = 0;
   4215   new->filesize = 0;
   4216   new->modificationdate = 0;
   4217   new->filetype = LIBMTP_FILETYPE_UNKNOWN;
   4218   new->next = NULL;
   4219   return new;
   4220 }
   4221 
   4222 /**
   4223  * This destroys a file metadata structure and deallocates the memory
   4224  * used by it, including any strings. Never use a file metadata
   4225  * structure again after calling this function on it.
   4226  * @param file the file metadata to destroy.
   4227  * @see LIBMTP_new_file_t()
   4228  */
   4229 void LIBMTP_destroy_file_t(LIBMTP_file_t *file)
   4230 {
   4231   if (file == NULL) {
   4232     return;
   4233   }
   4234   if (file->filename != NULL)
   4235     free(file->filename);
   4236   free(file);
   4237   return;
   4238 }
   4239 
   4240 /**
   4241  * Helper function that takes one PTP object and creates a
   4242  * LIBMTP_file_t metadata entry.
   4243  */
   4244 static LIBMTP_file_t *obj2file(LIBMTP_mtpdevice_t *device, PTPObject *ob)
   4245 {
   4246   PTPParams *params = (PTPParams *) device->params;
   4247   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   4248   LIBMTP_file_t *file;
   4249   int i;
   4250 
   4251   // Allocate a new file type
   4252   file = LIBMTP_new_file_t();
   4253 
   4254   file->parent_id = ob->oi.ParentObject;
   4255   file->storage_id = ob->oi.StorageID;
   4256 
   4257   // Set the filetype
   4258   file->filetype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
   4259 
   4260   /*
   4261    * A special quirk for devices that doesn't quite
   4262    * remember that some files marked as "unknown" type are
   4263    * actually OGG or FLAC files. We look at the filename extension
   4264    * and see if it happens that this was atleast named "ogg" or "flac"
   4265    * and fall back on this heuristic approach in that case,
   4266    * for these bugged devices only.
   4267    */
   4268   if (file->filetype == LIBMTP_FILETYPE_UNKNOWN) {
   4269     if ((FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
   4270 	 FLAG_OGG_IS_UNKNOWN(ptp_usb)) &&
   4271         has_ogg_extension(file->filename)) {
   4272       file->filetype = LIBMTP_FILETYPE_OGG;
   4273     }
   4274 
   4275     if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) && has_flac_extension(file->filename)) {
   4276         file->filetype = LIBMTP_FILETYPE_FLAC;
   4277     }
   4278   }
   4279 
   4280   // Set the modification date
   4281   file->modificationdate = ob->oi.ModificationDate;
   4282 
   4283   // We only have 32-bit file size here; later we use the PTP_OPC_ObjectSize property
   4284   file->filesize = ob->oi.ObjectCompressedSize;
   4285   if (ob->oi.Filename != NULL) {
   4286     file->filename = strdup(ob->oi.Filename);
   4287   }
   4288 
   4289   // This is a unique ID so we can keep track of the file.
   4290   file->item_id = ob->oid;
   4291 
   4292   /*
   4293    * If we have a cached, large set of metadata, then use it!
   4294    */
   4295   if (ob->mtpprops) {
   4296     MTPProperties *prop = ob->mtpprops;
   4297 
   4298     for (i=0; i < ob->nrofmtpprops; i++, prop++) {
   4299       // Pick ObjectSize here...
   4300       if (prop->property == PTP_OPC_ObjectSize) {
   4301 	// This may already be set, but this 64bit precision value
   4302 	// is better than the PTP 32bit value, so let it override.
   4303 	if (device->object_bitsize == 64) {
   4304 	  file->filesize = prop->propval.u64;
   4305 	} else {
   4306 	  file->filesize = prop->propval.u32;
   4307 	}
   4308 	break;
   4309       }
   4310     }
   4311   } else if (ptp_operation_issupported(params,PTP_OC_MTP_GetObjectPropsSupported)) {
   4312     uint16_t *props = NULL;
   4313     uint32_t propcnt = 0;
   4314     int ret;
   4315 
   4316     // First see which properties can be retrieved for this object format
   4317     ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(file->filetype), &propcnt, &props);
   4318     if (ret != PTP_RC_OK) {
   4319       add_ptp_error_to_errorstack(device, ret, "obj2file: call to ptp_mtp_getobjectpropssupported() failed.");
   4320       // Silently fall through.
   4321     } else {
   4322       for (i = 0; i < propcnt; i++) {
   4323 	switch (props[i]) {
   4324 	case PTP_OPC_ObjectSize:
   4325 	  if (device->object_bitsize == 64) {
   4326 	    file->filesize = get_u64_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
   4327 	  } else {
   4328 	    file->filesize = get_u32_from_object(device, file->item_id, PTP_OPC_ObjectSize, 0);
   4329 	  }
   4330 	  break;
   4331 	default:
   4332 	  break;
   4333 	}
   4334       }
   4335       free(props);
   4336     }
   4337   }
   4338 
   4339   return file;
   4340 }
   4341 
   4342 
   4343 /**
   4344  * This function retrieves the metadata for a single file off
   4345  * the device.
   4346  *
   4347  * Do not call this function repeatedly! The file handles are linearly
   4348  * searched O(n) and the call may involve (slow) USB traffic, so use
   4349  * <code>LIBMTP_Get_Filelisting()</code> and cache the file, preferably
   4350  * as an efficient data structure such as a hash list.
   4351  *
   4352  * Incidentally this function will return metadata for
   4353  * a folder (association) as well, but this is not a proper use
   4354  * of it, it is intended for file manipulation, not folder manipulation.
   4355  *
   4356  * @param device a pointer to the device to get the file metadata from.
   4357  * @param fileid the object ID of the file that you want the metadata for.
   4358  * @return a metadata entry on success or NULL on failure.
   4359  * @see LIBMTP_Get_Filelisting()
   4360  */
   4361 LIBMTP_file_t *LIBMTP_Get_Filemetadata(LIBMTP_mtpdevice_t *device, uint32_t const fileid)
   4362 {
   4363   PTPParams *params = (PTPParams *) device->params;
   4364   uint16_t ret;
   4365   PTPObject *ob;
   4366 
   4367   // Get all the handles if we haven't already done that
   4368   // (Only on cached devices.)
   4369   if (device->cached && params->nrofobjects == 0) {
   4370     flush_handles(device);
   4371   }
   4372 
   4373   ret = ptp_object_want(params, fileid, PTPOBJECT_OBJECTINFO_LOADED|PTPOBJECT_MTPPROPLIST_LOADED, &ob);
   4374   if (ret != PTP_RC_OK)
   4375     return NULL;
   4376 
   4377   return obj2file(device, ob);
   4378 }
   4379 
   4380 /**
   4381 * THIS FUNCTION IS DEPRECATED. PLEASE UPDATE YOUR CODE IN ORDER
   4382  * NOT TO USE IT.
   4383  * @see LIBMTP_Get_Filelisting_With_Callback()
   4384  */
   4385 LIBMTP_file_t *LIBMTP_Get_Filelisting(LIBMTP_mtpdevice_t *device)
   4386 {
   4387   LIBMTP_INFO("WARNING: LIBMTP_Get_Filelisting() is deprecated.\n");
   4388   LIBMTP_INFO("WARNING: please update your code to use LIBMTP_Get_Filelisting_With_Callback()\n");
   4389   return LIBMTP_Get_Filelisting_With_Callback(device, NULL, NULL);
   4390 }
   4391 
   4392 /**
   4393  * This returns a long list of all files available
   4394  * on the current MTP device. Folders will not be returned, but abstract
   4395  * entities like playlists and albums will show up as "files". Typical usage:
   4396  *
   4397  * <pre>
   4398  * LIBMTP_file_t *filelist;
   4399  *
   4400  * filelist = LIBMTP_Get_Filelisting_With_Callback(device, callback, data);
   4401  * while (filelist != NULL) {
   4402  *   LIBMTP_file_t *tmp;
   4403  *
   4404  *   // Do something on each element in the list here...
   4405  *   tmp = filelist;
   4406  *   filelist = filelist->next;
   4407  *   LIBMTP_destroy_file_t(tmp);
   4408  * }
   4409  * </pre>
   4410  *
   4411  * If you want to group your file listing by storage (per storage unit) or
   4412  * arrange files into folders, you must dereference the <code>storage_id</code>
   4413  * and/or <code>parent_id</code> field of the returned <code>LIBMTP_file_t</code>
   4414  * struct. To arrange by folders or files you typically have to create the proper
   4415  * trees by calls to <code>LIBMTP_Get_Storage()</code> and/or
   4416  * <code>LIBMTP_Get_Folder_List()</code> first.
   4417  *
   4418  * @param device a pointer to the device to get the file listing for.
   4419  * @param callback a function to be called during the tracklisting retrieveal
   4420  *        for displaying progress bars etc, or NULL if you don't want
   4421  *        any callbacks.
   4422  * @param data a user-defined pointer that is passed along to
   4423  *        the <code>progress</code> function in order to
   4424  *        pass along some user defined data to the progress
   4425  *        updates. If not used, set this to NULL.
   4426  * @return a list of files that can be followed using the <code>next</code>
   4427  *        field of the <code>LIBMTP_file_t</code> data structure.
   4428  *        Each of the metadata tags must be freed after use, and may
   4429  *        contain only partial metadata information, i.e. one or several
   4430  *        fields may be NULL or 0.
   4431  * @see LIBMTP_Get_Filemetadata()
   4432  */
   4433 LIBMTP_file_t *LIBMTP_Get_Filelisting_With_Callback(LIBMTP_mtpdevice_t *device,
   4434                                                     LIBMTP_progressfunc_t const callback,
   4435                                                     void const * const data)
   4436 {
   4437   uint32_t i = 0;
   4438   LIBMTP_file_t *retfiles = NULL;
   4439   LIBMTP_file_t *curfile = NULL;
   4440   PTPParams *params = (PTPParams *) device->params;
   4441 
   4442   // Get all the handles if we haven't already done that
   4443   if (params->nrofobjects == 0) {
   4444     flush_handles(device);
   4445   }
   4446 
   4447   for (i = 0; i < params->nrofobjects; i++) {
   4448     LIBMTP_file_t *file;
   4449     PTPObject *ob;
   4450 
   4451     if (callback != NULL)
   4452       callback(i, params->nrofobjects, data);
   4453 
   4454     ob = &params->objects[i];
   4455 
   4456     if (ob->oi.ObjectFormat == PTP_OFC_Association) {
   4457       // MTP use this object format for folders which means
   4458       // these "files" will turn up on a folder listing instead.
   4459       continue;
   4460     }
   4461 
   4462     // Look up metadata
   4463     file = obj2file(device, ob);
   4464     if (file == NULL) {
   4465       continue;
   4466     }
   4467 
   4468     // Add track to a list that will be returned afterwards.
   4469     if (retfiles == NULL) {
   4470       retfiles = file;
   4471       curfile = file;
   4472     } else {
   4473       curfile->next = file;
   4474       curfile = file;
   4475     }
   4476 
   4477     // Call listing callback
   4478     // double progressPercent = (double)i*(double)100.0 / (double)params->handles.n;
   4479 
   4480   } // Handle counting loop
   4481   return retfiles;
   4482 }
   4483 
   4484 /**
   4485  * This function retrieves the contents of a certain folder
   4486  * with id parent on a certain storage on a certain device.
   4487  * The result contains both files and folders.
   4488  * The device used with this operations must have been opened with
   4489  * LIBMTP_Open_Raw_Device_Uncached() or it will fail.
   4490  *
   4491  * NOTE: the request will always perform I/O with the device.
   4492  * @param device a pointer to the MTP device to report info from.
   4493  * @param storage a storage on the device to report info from. If
   4494  *        0 is passed in, the files for the given parent will be
   4495  *        searched across all available storages.
   4496  * @param parent the parent folder id.
   4497  */
   4498 LIBMTP_file_t * LIBMTP_Get_Files_And_Folders(LIBMTP_mtpdevice_t *device,
   4499 			     uint32_t const storage,
   4500 			     uint32_t const parent)
   4501 {
   4502   PTPParams *params = (PTPParams *) device->params;
   4503   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   4504   LIBMTP_file_t *retfiles = NULL;
   4505   LIBMTP_file_t *curfile = NULL;
   4506   PTPObjectHandles currentHandles;
   4507   uint32_t storageid;
   4508   uint16_t ret;
   4509   int i = 0;
   4510 
   4511   if (device->cached) {
   4512     // This function is only supposed to be used by devices
   4513     // opened as uncached!
   4514     LIBMTP_ERROR("tried to use %s on a cached device!\n",
   4515 		 __func__);
   4516     return NULL;
   4517   }
   4518 
   4519   if (FLAG_BROKEN_GET_OBJECT_PROPVAL(ptp_usb)) {
   4520     // These devices cannot handle the commands needed for
   4521     // Uncached access!
   4522     LIBMTP_ERROR("tried to use %s on an unsupported device, "
   4523 		 "this command does not work on all devices "
   4524 		 "due to missing low-level support to read "
   4525 		 "information on individual tracks\n",
   4526 		 __func__);
   4527     return NULL;
   4528   }
   4529 
   4530   if (storage == 0)
   4531     storageid = PTP_GOH_ALL_STORAGE;
   4532   else
   4533     storageid = storage;
   4534 
   4535   ret = ptp_getobjecthandles(params,
   4536 			     storageid,
   4537 			     PTP_GOH_ALL_FORMATS,
   4538 			     parent,
   4539 			     &currentHandles);
   4540 
   4541   if (ret != PTP_RC_OK) {
   4542     add_ptp_error_to_errorstack(device, ret,
   4543 		"LIBMTP_Get_Files_And_Folders(): could not get object handles.");
   4544     return NULL;
   4545   }
   4546 
   4547   if (currentHandles.Handler == NULL || currentHandles.n == 0)
   4548     return NULL;
   4549 
   4550   for (i = 0; i < currentHandles.n; i++) {
   4551     LIBMTP_file_t *file;
   4552 
   4553     // Get metadata for one file, if it fails, try next file
   4554     file = LIBMTP_Get_Filemetadata(device, currentHandles.Handler[i]);
   4555     if (file == NULL)
   4556       continue;
   4557 
   4558     // Add track to a list that will be returned afterwards.
   4559     if (curfile == NULL) {
   4560       curfile = file;
   4561       retfiles = file;
   4562     } else {
   4563       curfile->next = file;
   4564       curfile = file;
   4565     }
   4566   }
   4567 
   4568   free(currentHandles.Handler);
   4569 
   4570   // Return a pointer to the original first file
   4571   // in the big list.
   4572   return retfiles;
   4573 }
   4574 
   4575 void LIBMTP_Set_Load_Cache_On_Demand(int flag)
   4576 {
   4577   load_cache_on_demand = flag;
   4578 }
   4579 
   4580 /**
   4581  * This creates a new track metadata structure and allocates memory
   4582  * for it. Notice that if you add strings to this structure they
   4583  * will be freed by the corresponding <code>LIBMTP_destroy_track_t</code>
   4584  * operation later, so be careful of using strdup() when assigning
   4585  * strings, e.g.:
   4586  *
   4587  * <pre>
   4588  * LIBMTP_track_t *track = LIBMTP_new_track_t();
   4589  * track->title = strdup(titlestr);
   4590  * ....
   4591  * LIBMTP_destroy_track_t(track);
   4592  * </pre>
   4593  *
   4594  * @return a pointer to the newly allocated metadata structure.
   4595  * @see LIBMTP_destroy_track_t()
   4596  */
   4597 LIBMTP_track_t *LIBMTP_new_track_t(void)
   4598 {
   4599   LIBMTP_track_t *new = (LIBMTP_track_t *) malloc(sizeof(LIBMTP_track_t));
   4600   if (new == NULL) {
   4601     return NULL;
   4602   }
   4603   new->item_id = 0;
   4604   new->parent_id = 0;
   4605   new->storage_id = 0;
   4606   new->title = NULL;
   4607   new->artist = NULL;
   4608   new->composer = NULL;
   4609   new->album = NULL;
   4610   new->genre = NULL;
   4611   new->date = NULL;
   4612   new->filename = NULL;
   4613   new->duration = 0;
   4614   new->tracknumber = 0;
   4615   new->filesize = 0;
   4616   new->filetype = LIBMTP_FILETYPE_UNKNOWN;
   4617   new->samplerate = 0;
   4618   new->nochannels = 0;
   4619   new->wavecodec = 0;
   4620   new->bitrate = 0;
   4621   new->bitratetype = 0;
   4622   new->rating = 0;
   4623   new->usecount = 0;
   4624   new->modificationdate = 0;
   4625   new->next = NULL;
   4626   return new;
   4627 }
   4628 
   4629 /**
   4630  * This destroys a track metadata structure and deallocates the memory
   4631  * used by it, including any strings. Never use a track metadata
   4632  * structure again after calling this function on it.
   4633  * @param track the track metadata to destroy.
   4634  * @see LIBMTP_new_track_t()
   4635  */
   4636 void LIBMTP_destroy_track_t(LIBMTP_track_t *track)
   4637 {
   4638   if (track == NULL) {
   4639     return;
   4640   }
   4641   if (track->title != NULL)
   4642     free(track->title);
   4643   if (track->artist != NULL)
   4644     free(track->artist);
   4645   if (track->composer != NULL)
   4646     free(track->composer);
   4647   if (track->album != NULL)
   4648     free(track->album);
   4649   if (track->genre != NULL)
   4650     free(track->genre);
   4651   if (track->date != NULL)
   4652     free(track->date);
   4653   if (track->filename != NULL)
   4654     free(track->filename);
   4655   free(track);
   4656   return;
   4657 }
   4658 
   4659 /**
   4660  * This function maps and copies a property onto the track metadata if applicable.
   4661  */
   4662 static void pick_property_to_track_metadata(LIBMTP_mtpdevice_t *device, MTPProperties *prop, LIBMTP_track_t *track)
   4663 {
   4664   switch (prop->property) {
   4665   case PTP_OPC_Name:
   4666     if (prop->propval.str != NULL)
   4667       track->title = strdup(prop->propval.str);
   4668     else
   4669       track->title = NULL;
   4670     break;
   4671   case PTP_OPC_Artist:
   4672     if (prop->propval.str != NULL)
   4673       track->artist = strdup(prop->propval.str);
   4674     else
   4675       track->artist = NULL;
   4676     break;
   4677   case PTP_OPC_Composer:
   4678     if (prop->propval.str != NULL)
   4679       track->composer = strdup(prop->propval.str);
   4680     else
   4681       track->composer = NULL;
   4682     break;
   4683   case PTP_OPC_Duration:
   4684     track->duration = prop->propval.u32;
   4685     break;
   4686   case PTP_OPC_Track:
   4687     track->tracknumber = prop->propval.u16;
   4688     break;
   4689   case PTP_OPC_Genre:
   4690     if (prop->propval.str != NULL)
   4691       track->genre = strdup(prop->propval.str);
   4692     else
   4693       track->genre = NULL;
   4694     break;
   4695   case PTP_OPC_AlbumName:
   4696     if (prop->propval.str != NULL)
   4697       track->album = strdup(prop->propval.str);
   4698     else
   4699       track->album = NULL;
   4700     break;
   4701   case PTP_OPC_OriginalReleaseDate:
   4702     if (prop->propval.str != NULL)
   4703       track->date = strdup(prop->propval.str);
   4704     else
   4705       track->date = NULL;
   4706     break;
   4707     // These are, well not so important.
   4708   case PTP_OPC_SampleRate:
   4709     track->samplerate = prop->propval.u32;
   4710     break;
   4711   case PTP_OPC_NumberOfChannels:
   4712     track->nochannels = prop->propval.u16;
   4713     break;
   4714   case PTP_OPC_AudioWAVECodec:
   4715     track->wavecodec = prop->propval.u32;
   4716     break;
   4717   case PTP_OPC_AudioBitRate:
   4718     track->bitrate = prop->propval.u32;
   4719     break;
   4720   case PTP_OPC_BitRateType:
   4721     track->bitratetype = prop->propval.u16;
   4722     break;
   4723   case PTP_OPC_Rating:
   4724     track->rating = prop->propval.u16;
   4725     break;
   4726   case PTP_OPC_UseCount:
   4727     track->usecount = prop->propval.u32;
   4728     break;
   4729   case PTP_OPC_ObjectSize:
   4730     if (device->object_bitsize == 64) {
   4731       track->filesize = prop->propval.u64;
   4732     } else {
   4733       track->filesize = prop->propval.u32;
   4734     }
   4735     break;
   4736   default:
   4737     break;
   4738   }
   4739 }
   4740 
   4741 /**
   4742  * This function retrieves the track metadata for a track
   4743  * given by a unique ID.
   4744  * @param device a pointer to the device to get the track metadata off.
   4745  * @param trackid the unique ID of the track.
   4746  * @param objectformat the object format of this track, so we know what it supports.
   4747  * @param track a metadata set to fill in.
   4748  */
   4749 static void get_track_metadata(LIBMTP_mtpdevice_t *device, uint16_t objectformat,
   4750 			       LIBMTP_track_t *track)
   4751 {
   4752   uint16_t ret;
   4753   PTPParams *params = (PTPParams *) device->params;
   4754   uint32_t i;
   4755   MTPProperties *prop;
   4756   PTPObject *ob;
   4757 
   4758   /*
   4759    * If we have a cached, large set of metadata, then use it!
   4760    */
   4761   ret = ptp_object_want(params, track->item_id, PTPOBJECT_MTPPROPLIST_LOADED, &ob);
   4762   if (ob->mtpprops) {
   4763     prop = ob->mtpprops;
   4764     for (i=0;i<ob->nrofmtpprops;i++,prop++)
   4765       pick_property_to_track_metadata(device, prop, track);
   4766   } else {
   4767     uint16_t *props = NULL;
   4768     uint32_t propcnt = 0;
   4769 
   4770     // First see which properties can be retrieved for this object format
   4771     ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(track->filetype), &propcnt, &props);
   4772     if (ret != PTP_RC_OK) {
   4773       add_ptp_error_to_errorstack(device, ret, "get_track_metadata(): call to ptp_mtp_getobjectpropssupported() failed.");
   4774       // Just bail out for now, nothing is ever set.
   4775       return;
   4776     } else {
   4777       for (i=0;i<propcnt;i++) {
   4778 	switch (props[i]) {
   4779 	case PTP_OPC_Name:
   4780 	  track->title = get_string_from_object(device, track->item_id, PTP_OPC_Name);
   4781 	  break;
   4782 	case PTP_OPC_Artist:
   4783 	  track->artist = get_string_from_object(device, track->item_id, PTP_OPC_Artist);
   4784 	  break;
   4785 	case PTP_OPC_Composer:
   4786 	  track->composer = get_string_from_object(device, track->item_id, PTP_OPC_Composer);
   4787 	  break;
   4788 	case PTP_OPC_Duration:
   4789 	  track->duration = get_u32_from_object(device, track->item_id, PTP_OPC_Duration, 0);
   4790 	  break;
   4791 	case PTP_OPC_Track:
   4792 	  track->tracknumber = get_u16_from_object(device, track->item_id, PTP_OPC_Track, 0);
   4793 	  break;
   4794 	case PTP_OPC_Genre:
   4795 	  track->genre = get_string_from_object(device, track->item_id, PTP_OPC_Genre);
   4796 	  break;
   4797 	case PTP_OPC_AlbumName:
   4798 	  track->album = get_string_from_object(device, track->item_id, PTP_OPC_AlbumName);
   4799 	  break;
   4800 	case PTP_OPC_OriginalReleaseDate:
   4801 	  track->date = get_string_from_object(device, track->item_id, PTP_OPC_OriginalReleaseDate);
   4802 	  break;
   4803 	  // These are, well not so important.
   4804 	case PTP_OPC_SampleRate:
   4805 	  track->samplerate = get_u32_from_object(device, track->item_id, PTP_OPC_SampleRate, 0);
   4806 	  break;
   4807 	case PTP_OPC_NumberOfChannels:
   4808 	  track->nochannels = get_u16_from_object(device, track->item_id, PTP_OPC_NumberOfChannels, 0);
   4809 	  break;
   4810 	case PTP_OPC_AudioWAVECodec:
   4811 	  track->wavecodec = get_u32_from_object(device, track->item_id, PTP_OPC_AudioWAVECodec, 0);
   4812 	  break;
   4813 	case PTP_OPC_AudioBitRate:
   4814 	  track->bitrate = get_u32_from_object(device, track->item_id, PTP_OPC_AudioBitRate, 0);
   4815 	  break;
   4816 	case PTP_OPC_BitRateType:
   4817 	  track->bitratetype = get_u16_from_object(device, track->item_id, PTP_OPC_BitRateType, 0);
   4818 	  break;
   4819 	case PTP_OPC_Rating:
   4820 	  track->rating = get_u16_from_object(device, track->item_id, PTP_OPC_Rating, 0);
   4821 	  break;
   4822 	case PTP_OPC_UseCount:
   4823 	  track->usecount = get_u32_from_object(device, track->item_id, PTP_OPC_UseCount, 0);
   4824 	  break;
   4825 	case PTP_OPC_ObjectSize:
   4826 	  if (device->object_bitsize == 64) {
   4827 	    track->filesize = get_u64_from_object(device, track->item_id, PTP_OPC_ObjectSize, 0);
   4828 	  } else {
   4829 	    track->filesize = (uint64_t) get_u32_from_object(device, track->item_id, PTP_OPC_ObjectSize, 0);
   4830 	  }
   4831 	  break;
   4832 	}
   4833       }
   4834       free(props);
   4835     }
   4836   }
   4837 }
   4838 
   4839 /**
   4840  * THIS FUNCTION IS DEPRECATED. PLEASE UPDATE YOUR CODE IN ORDER
   4841  * NOT TO USE IT.
   4842  * @see LIBMTP_Get_Tracklisting_With_Callback()
   4843  */
   4844 LIBMTP_track_t *LIBMTP_Get_Tracklisting(LIBMTP_mtpdevice_t *device)
   4845 {
   4846   LIBMTP_INFO("WARNING: LIBMTP_Get_Tracklisting() is deprecated.\n");
   4847   LIBMTP_INFO("WARNING: please update your code to use LIBMTP_Get_Tracklisting_With_Callback()\n");
   4848   return LIBMTP_Get_Tracklisting_With_Callback(device, NULL, NULL);
   4849 }
   4850 
   4851 /**
   4852  * This returns a long list of all tracks available on the current MTP device.
   4853  * Tracks include multimedia objects, both music tracks and video tracks.
   4854  * Typical usage:
   4855  *
   4856  * <pre>
   4857  * LIBMTP_track_t *tracklist;
   4858  *
   4859  * tracklist = LIBMTP_Get_Tracklisting_With_Callback(device, callback, data);
   4860  * while (tracklist != NULL) {
   4861  *   LIBMTP_track_t *tmp;
   4862  *
   4863  *   // Do something on each element in the list here...
   4864  *   tmp = tracklist;
   4865  *   tracklist = tracklist->next;
   4866  *   LIBMTP_destroy_track_t(tmp);
   4867  * }
   4868  * </pre>
   4869  *
   4870  * If you want to group your track listing by storage (per storage unit) or
   4871  * arrange tracks into folders, you must dereference the <code>storage_id</code>
   4872  * and/or <code>parent_id</code> field of the returned <code>LIBMTP_track_t</code>
   4873  * struct. To arrange by folders or files you typically have to create the proper
   4874  * trees by calls to <code>LIBMTP_Get_Storage()</code> and/or
   4875  * <code>LIBMTP_Get_Folder_List()</code> first.
   4876  *
   4877  * @param device a pointer to the device to get the track listing for.
   4878  * @param callback a function to be called during the tracklisting retrieveal
   4879  *        for displaying progress bars etc, or NULL if you don't want
   4880  *        any callbacks.
   4881  * @param data a user-defined pointer that is passed along to
   4882  *        the <code>progress</code> function in order to
   4883  *        pass along some user defined data to the progress
   4884  *        updates. If not used, set this to NULL.
   4885  * @return a list of tracks that can be followed using the <code>next</code>
   4886  *        field of the <code>LIBMTP_track_t</code> data structure.
   4887  *        Each of the metadata tags must be freed after use, and may
   4888  *        contain only partial metadata information, i.e. one or several
   4889  *        fields may be NULL or 0.
   4890  * @see LIBMTP_Get_Trackmetadata()
   4891  */
   4892 LIBMTP_track_t *LIBMTP_Get_Tracklisting_With_Callback(LIBMTP_mtpdevice_t *device,
   4893                                                       LIBMTP_progressfunc_t const callback,
   4894                                                       void const * const data)
   4895 {
   4896 	return LIBMTP_Get_Tracklisting_With_Callback_For_Storage(device, 0, callback, data);
   4897 }
   4898 
   4899 
   4900 /**
   4901  * This returns a long list of all tracks available on the current MTP device.
   4902  * Tracks include multimedia objects, both music tracks and video tracks.
   4903  * Typical usage:
   4904  *
   4905  * <pre>
   4906  * LIBMTP_track_t *tracklist;
   4907  *
   4908  * tracklist = LIBMTP_Get_Tracklisting_With_Callback_For_Storage(device, storage_id, callback, data);
   4909  * while (tracklist != NULL) {
   4910  *   LIBMTP_track_t *tmp;
   4911  *
   4912  *   // Do something on each element in the list here...
   4913  *   tmp = tracklist;
   4914  *   tracklist = tracklist->next;
   4915  *   LIBMTP_destroy_track_t(tmp);
   4916  * }
   4917  * </pre>
   4918  *
   4919  * If you want to group your track listing by storage (per storage unit) or
   4920  * arrange tracks into folders, you must dereference the <code>storage_id</code>
   4921  * and/or <code>parent_id</code> field of the returned <code>LIBMTP_track_t</code>
   4922  * struct. To arrange by folders or files you typically have to create the proper
   4923  * trees by calls to <code>LIBMTP_Get_Storage()</code> and/or
   4924  * <code>LIBMTP_Get_Folder_List()</code> first.
   4925  *
   4926  * @param device a pointer to the device to get the track listing for.
   4927  * @param storage_id ID of device storage (if null, no filter)
   4928  * @param callback a function to be called during the tracklisting retrieveal
   4929  *        for displaying progress bars etc, or NULL if you don't want
   4930  *        any callbacks.
   4931  * @param data a user-defined pointer that is passed along to
   4932  *        the <code>progress</code> function in order to
   4933  *        pass along some user defined data to the progress
   4934  *        updates. If not used, set this to NULL.
   4935  * @return a list of tracks that can be followed using the <code>next</code>
   4936  *        field of the <code>LIBMTP_track_t</code> data structure.
   4937  *        Each of the metadata tags must be freed after use, and may
   4938  *        contain only partial metadata information, i.e. one or several
   4939  *        fields may be NULL or 0.
   4940  * @see LIBMTP_Get_Trackmetadata()
   4941  */
   4942 LIBMTP_track_t *LIBMTP_Get_Tracklisting_With_Callback_For_Storage(LIBMTP_mtpdevice_t *device, uint32_t const storage_id,
   4943                                                       LIBMTP_progressfunc_t const callback,
   4944                                                       void const * const data)
   4945 {
   4946   uint32_t i = 0;
   4947   LIBMTP_track_t *retracks = NULL;
   4948   LIBMTP_track_t *curtrack = NULL;
   4949   PTPParams *params = (PTPParams *) device->params;
   4950   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   4951 
   4952   // Get all the handles if we haven't already done that
   4953   if (params->nrofobjects == 0) {
   4954     flush_handles(device);
   4955   }
   4956 
   4957   for (i = 0; i < params->nrofobjects; i++) {
   4958     LIBMTP_track_t *track;
   4959     PTPObject *ob;
   4960     LIBMTP_filetype_t mtptype;
   4961 
   4962     if (callback != NULL)
   4963       callback(i, params->nrofobjects, data);
   4964 
   4965     ob = &params->objects[i];
   4966     mtptype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
   4967 
   4968     // Ignore stuff we don't know how to handle...
   4969     // TODO: get this list as an intersection of the sets
   4970     // supported by the device and the from the device and
   4971     // all known track files?
   4972     if (!LIBMTP_FILETYPE_IS_TRACK(mtptype) &&
   4973 	// This row lets through undefined files for examination since they may be forgotten OGG files.
   4974 	(ob->oi.ObjectFormat != PTP_OFC_Undefined ||
   4975 	 (!FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) &&
   4976 	  !FLAG_OGG_IS_UNKNOWN(ptp_usb) &&
   4977 	  !FLAG_FLAC_IS_UNKNOWN(ptp_usb)))
   4978 	) {
   4979       //printf("Not a music track (name: %s format: %d), skipping...\n", oi->Filename, oi->ObjectFormat);
   4980       continue;
   4981     }
   4982 
   4983 	// Ignore stuff that isn't into the storage device
   4984 	if ((storage_id != 0) && (ob->oi.StorageID != storage_id ))
   4985 		continue;
   4986 
   4987     // Allocate a new track type
   4988     track = LIBMTP_new_track_t();
   4989 
   4990     // This is some sort of unique ID so we can keep track of the track.
   4991     track->item_id = ob->oid;
   4992     track->parent_id = ob->oi.ParentObject;
   4993     track->storage_id = ob->oi.StorageID;
   4994     track->modificationdate = ob->oi.ModificationDate;
   4995 
   4996     track->filetype = mtptype;
   4997 
   4998     // Original file-specific properties
   4999     track->filesize = ob->oi.ObjectCompressedSize;
   5000     if (ob->oi.Filename != NULL) {
   5001       track->filename = strdup(ob->oi.Filename);
   5002     }
   5003 
   5004     get_track_metadata(device, ob->oi.ObjectFormat, track);
   5005 
   5006     /*
   5007      * A special quirk for iriver devices that doesn't quite
   5008      * remember that some files marked as "unknown" type are
   5009      * actually OGG or FLAC files. We look at the filename extension
   5010      * and see if it happens that this was atleast named "ogg" or "flac"
   5011      * and fall back on this heuristic approach in that case,
   5012      * for these bugged devices only.
   5013      */
   5014     if (track->filetype == LIBMTP_FILETYPE_UNKNOWN &&
   5015 	track->filename != NULL) {
   5016       if ((FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
   5017 	   FLAG_OGG_IS_UNKNOWN(ptp_usb)) &&
   5018 	  has_ogg_extension(track->filename))
   5019 	track->filetype = LIBMTP_FILETYPE_OGG;
   5020       else if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) &&
   5021 	       has_flac_extension(track->filename))
   5022 	track->filetype = LIBMTP_FILETYPE_FLAC;
   5023       else {
   5024 	// This was not an OGG/FLAC file so discard it and continue
   5025 	LIBMTP_destroy_track_t(track);
   5026 	continue;
   5027       }
   5028     }
   5029 
   5030     // Add track to a list that will be returned afterwards.
   5031     if (retracks == NULL) {
   5032       retracks = track;
   5033       curtrack = track;
   5034     } else {
   5035       curtrack->next = track;
   5036       curtrack = track;
   5037     }
   5038 
   5039     // Call listing callback
   5040     // double progressPercent = (double)i*(double)100.0 / (double)params->handles.n;
   5041 
   5042   } // Handle counting loop
   5043   return retracks;
   5044 }
   5045 
   5046 /**
   5047  * This function retrieves the metadata for a single track off
   5048  * the device.
   5049  *
   5050  * Do not call this function repeatedly! The track handles are linearly
   5051  * searched O(n) and the call may involve (slow) USB traffic, so use
   5052  * <code>LIBMTP_Get_Tracklisting()</code> and cache the tracks, preferably
   5053  * as an efficient data structure such as a hash list.
   5054  *
   5055  * @param device a pointer to the device to get the track metadata from.
   5056  * @param trackid the object ID of the track that you want the metadata for.
   5057  * @return a track metadata entry on success or NULL on failure.
   5058  * @see LIBMTP_Get_Tracklisting()
   5059  */
   5060 LIBMTP_track_t *LIBMTP_Get_Trackmetadata(LIBMTP_mtpdevice_t *device, uint32_t const trackid)
   5061 {
   5062   PTPParams *params = (PTPParams *) device->params;
   5063   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   5064   PTPObject *ob;
   5065   LIBMTP_track_t *track;
   5066   LIBMTP_filetype_t mtptype;
   5067   uint16_t ret;
   5068 
   5069   // Get all the handles if we haven't already done that
   5070   if (params->nrofobjects == 0)
   5071     flush_handles(device);
   5072 
   5073   ret = ptp_object_want (params, trackid, PTPOBJECT_OBJECTINFO_LOADED, &ob);
   5074   if (ret != PTP_RC_OK)
   5075     return NULL;
   5076 
   5077   mtptype = map_ptp_type_to_libmtp_type(ob->oi.ObjectFormat);
   5078 
   5079   // Ignore stuff we don't know how to handle...
   5080   if (!LIBMTP_FILETYPE_IS_TRACK(mtptype) &&
   5081       /*
   5082        * This row lets through undefined files for examination
   5083        * since they may be forgotten OGG or FLAC files.
   5084        */
   5085       (ob->oi.ObjectFormat != PTP_OFC_Undefined ||
   5086        (!FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) &&
   5087 	!FLAG_OGG_IS_UNKNOWN(ptp_usb) &&
   5088 	!FLAG_FLAC_IS_UNKNOWN(ptp_usb)))
   5089       ) {
   5090     //printf("Not a music track (name: %s format: %d), skipping...\n", oi->Filename, oi->ObjectFormat);
   5091     return NULL;
   5092   }
   5093 
   5094   // Allocate a new track type
   5095   track = LIBMTP_new_track_t();
   5096 
   5097   // This is some sort of unique ID so we can keep track of the track.
   5098   track->item_id = ob->oid;
   5099   track->parent_id = ob->oi.ParentObject;
   5100   track->storage_id = ob->oi.StorageID;
   5101   track->modificationdate = ob->oi.ModificationDate;
   5102 
   5103   track->filetype = mtptype;
   5104 
   5105   // Original file-specific properties
   5106   track->filesize = ob->oi.ObjectCompressedSize;
   5107   if (ob->oi.Filename != NULL) {
   5108     track->filename = strdup(ob->oi.Filename);
   5109   }
   5110 
   5111   /*
   5112    * A special quirk for devices that doesn't quite
   5113    * remember that some files marked as "unknown" type are
   5114    * actually OGG or FLAC files. We look at the filename extension
   5115    * and see if it happens that this was atleast named "ogg"
   5116    * and fall back on this heuristic approach in that case,
   5117    * for these bugged devices only.
   5118    */
   5119   if (track->filetype == LIBMTP_FILETYPE_UNKNOWN &&
   5120       track->filename != NULL) {
   5121     if ((FLAG_IRIVER_OGG_ALZHEIMER(ptp_usb) ||
   5122 	 FLAG_OGG_IS_UNKNOWN(ptp_usb)) &&
   5123 	has_ogg_extension(track->filename))
   5124       track->filetype = LIBMTP_FILETYPE_OGG;
   5125     else if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) &&
   5126 	     has_flac_extension(track->filename))
   5127       track->filetype = LIBMTP_FILETYPE_FLAC;
   5128     else {
   5129       // This was not an OGG/FLAC file so discard it
   5130       LIBMTP_destroy_track_t(track);
   5131       return NULL;
   5132     }
   5133   }
   5134   get_track_metadata(device, ob->oi.ObjectFormat, track);
   5135   return track;
   5136 }
   5137 
   5138 /**
   5139  * This is a manual conversion from MTPDataGetFunc to PTPDataGetFunc
   5140  * to isolate the internal type.
   5141  */
   5142 static uint16_t get_func_wrapper(PTPParams* params, void* priv, unsigned long wantlen, unsigned char *data, unsigned long *gotlen)
   5143 {
   5144   MTPDataHandler *handler = (MTPDataHandler *)priv;
   5145   uint16_t ret;
   5146   uint32_t local_gotlen = 0;
   5147   ret = handler->getfunc(params, handler->priv, wantlen, data, &local_gotlen);
   5148   *gotlen = local_gotlen;
   5149   switch (ret)
   5150   {
   5151     case LIBMTP_HANDLER_RETURN_OK:
   5152       return PTP_RC_OK;
   5153     case LIBMTP_HANDLER_RETURN_ERROR:
   5154       return PTP_ERROR_IO;
   5155     case LIBMTP_HANDLER_RETURN_CANCEL:
   5156       return PTP_ERROR_CANCEL;
   5157     default:
   5158       return PTP_ERROR_IO;
   5159   }
   5160 }
   5161 
   5162 /**
   5163  * This is a manual conversion from MTPDataPutFunc to PTPDataPutFunc
   5164  * to isolate the internal type.
   5165  */
   5166 static uint16_t put_func_wrapper(PTPParams* params, void* priv, unsigned long sendlen, unsigned char *data)
   5167 {
   5168   MTPDataHandler *handler = (MTPDataHandler *)priv;
   5169   uint16_t ret;
   5170   uint32_t local_putlen = 0;
   5171 
   5172   ret = handler->putfunc(params, handler->priv, sendlen, data, &local_putlen);
   5173 
   5174   switch (ret)
   5175   {
   5176     case LIBMTP_HANDLER_RETURN_OK:
   5177       if (local_putlen != sendlen)
   5178 	return PTP_ERROR_IO;
   5179       return PTP_RC_OK;
   5180     case LIBMTP_HANDLER_RETURN_ERROR:
   5181       return PTP_ERROR_IO;
   5182     case LIBMTP_HANDLER_RETURN_CANCEL:
   5183       return PTP_ERROR_CANCEL;
   5184     default:
   5185       return PTP_ERROR_IO;
   5186   }
   5187 }
   5188 
   5189 /**
   5190  * This gets a file off the device to a local file identified
   5191  * by a filename.
   5192  * @param device a pointer to the device to get the track from.
   5193  * @param id the file ID of the file to retrieve.
   5194  * @param path a filename to use for the retrieved file.
   5195  * @param callback a progress indicator function or NULL to ignore.
   5196  * @param data a user-defined pointer that is passed along to
   5197  *             the <code>progress</code> function in order to
   5198  *             pass along some user defined data to the progress
   5199  *             updates. If not used, set this to NULL.
   5200  * @return 0 if the transfer was successful, any other value means
   5201  *           failure.
   5202  * @see LIBMTP_Get_File_To_File_Descriptor()
   5203  */
   5204 int LIBMTP_Get_File_To_File(LIBMTP_mtpdevice_t *device, uint32_t const id,
   5205 			 char const * const path, LIBMTP_progressfunc_t const callback,
   5206 			 void const * const data)
   5207 {
   5208   int fd = -1;
   5209   int ret;
   5210 
   5211   // Sanity check
   5212   if (path == NULL) {
   5213     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File(): Bad arguments, path was NULL.");
   5214     return -1;
   5215   }
   5216 
   5217   // Open file
   5218 #ifdef __WIN32__
   5219 #ifdef USE_WINDOWS_IO_H
   5220   if ( (fd = _open(path, O_RDWR|O_CREAT|O_TRUNC|O_BINARY,_S_IREAD)) == -1 ) {
   5221 #else
   5222   if ( (fd = open(path, O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IRWXU)) == -1 ) {
   5223 #endif
   5224 #else
   5225   if ( (fd = open(path, O_RDWR|O_CREAT|O_TRUNC,S_IRWXU|S_IRGRP)) == -1) {
   5226 #endif
   5227     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File(): Could not create file.");
   5228     return -1;
   5229   }
   5230 
   5231   ret = LIBMTP_Get_File_To_File_Descriptor(device, id, fd, callback, data);
   5232 
   5233   // Close file
   5234   close(fd);
   5235 
   5236   // Delete partial file.
   5237   if (ret == -1) {
   5238     unlink(path);
   5239   }
   5240 
   5241   return ret;
   5242 }
   5243 
   5244 /**
   5245  * This gets a file off the device to a file identified
   5246  * by a file descriptor.
   5247  *
   5248  * This function can potentially be used for streaming
   5249  * files off the device for playback or broadcast for example,
   5250  * by downloading the file into a stream sink e.g. a socket.
   5251  *
   5252  * @param device a pointer to the device to get the file from.
   5253  * @param id the file ID of the file to retrieve.
   5254  * @param fd a local file descriptor to write the file to.
   5255  * @param callback a progress indicator function or NULL to ignore.
   5256  * @param data a user-defined pointer that is passed along to
   5257  *             the <code>progress</code> function in order to
   5258  *             pass along some user defined data to the progress
   5259  *             updates. If not used, set this to NULL.
   5260  * @return 0 if the transfer was successful, any other value means
   5261  *           failure.
   5262  * @see LIBMTP_Get_File_To_File()
   5263  */
   5264 int LIBMTP_Get_File_To_File_Descriptor(LIBMTP_mtpdevice_t *device,
   5265 					uint32_t const id,
   5266 					int const fd,
   5267 					LIBMTP_progressfunc_t const callback,
   5268 					void const * const data)
   5269 {
   5270   uint16_t ret;
   5271   PTPParams *params = (PTPParams *) device->params;
   5272   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   5273   PTPObject *ob;
   5274 
   5275   ret = ptp_object_want (params, id, PTPOBJECT_OBJECTINFO_LOADED, &ob);
   5276   if (ret != PTP_RC_OK) {
   5277     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File_Descriptor(): Could not get object info.");
   5278     return -1;
   5279   }
   5280   if (ob->oi.ObjectFormat == PTP_OFC_Association) {
   5281     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File_Descriptor(): Bad object format.");
   5282     return -1;
   5283   }
   5284 
   5285   // Callbacks
   5286   ptp_usb->callback_active = 1;
   5287   ptp_usb->current_transfer_total = ob->oi.ObjectCompressedSize+
   5288     PTP_USB_BULK_HDR_LEN+sizeof(uint32_t); // Request length, one parameter
   5289   ptp_usb->current_transfer_complete = 0;
   5290   ptp_usb->current_transfer_callback = callback;
   5291   ptp_usb->current_transfer_callback_data = data;
   5292 
   5293   ret = ptp_getobject_tofd(params, id, fd);
   5294 
   5295   ptp_usb->callback_active = 0;
   5296   ptp_usb->current_transfer_callback = NULL;
   5297   ptp_usb->current_transfer_callback_data = NULL;
   5298 
   5299   if (ret == PTP_ERROR_CANCEL) {
   5300     add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Get_File_From_File_Descriptor(): Cancelled transfer.");
   5301     return -1;
   5302   }
   5303   if (ret != PTP_RC_OK) {
   5304     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_File_To_File_Descriptor(): Could not get file from device.");
   5305     return -1;
   5306   }
   5307 
   5308   return 0;
   5309 }
   5310 
   5311 /**
   5312  * This gets a file off the device and calls put_func
   5313  * with chunks of data
   5314  *
   5315  * @param device a pointer to the device to get the file from.
   5316  * @param id the file ID of the file to retrieve.
   5317  * @param put_func the function to call when we have data.
   5318  * @param priv the user-defined pointer that is passed to
   5319  *             <code>put_func</code>.
   5320  * @param callback a progress indicator function or NULL to ignore.
   5321  * @param data a user-defined pointer that is passed along to
   5322  *             the <code>progress</code> function in order to
   5323  *             pass along some user defined data to the progress
   5324  *             updates. If not used, set this to NULL.
   5325  * @return 0 if the transfer was successful, any other value means
   5326  *           failure.
   5327  */
   5328 int LIBMTP_Get_File_To_Handler(LIBMTP_mtpdevice_t *device,
   5329 					uint32_t const id,
   5330 					MTPDataPutFunc put_func,
   5331           void * priv,
   5332 					LIBMTP_progressfunc_t const callback,
   5333 					void const * const data)
   5334 {
   5335   PTPObject *ob;
   5336   uint16_t ret;
   5337   PTPParams *params = (PTPParams *) device->params;
   5338   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   5339 
   5340   ret = ptp_object_want (params, id, PTPOBJECT_OBJECTINFO_LOADED, &ob);
   5341   if (ret != PTP_RC_OK) {
   5342     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File_Descriptor(): Could not get object info.");
   5343     return -1;
   5344   }
   5345   if (ob->oi.ObjectFormat == PTP_OFC_Association) {
   5346     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_File_To_File_Descriptor(): Bad object format.");
   5347     return -1;
   5348   }
   5349 
   5350   // Callbacks
   5351   ptp_usb->callback_active = 1;
   5352   ptp_usb->current_transfer_total = ob->oi.ObjectCompressedSize+
   5353     PTP_USB_BULK_HDR_LEN+sizeof(uint32_t); // Request length, one parameter
   5354   ptp_usb->current_transfer_complete = 0;
   5355   ptp_usb->current_transfer_callback = callback;
   5356   ptp_usb->current_transfer_callback_data = data;
   5357 
   5358   MTPDataHandler mtp_handler;
   5359   mtp_handler.getfunc = NULL;
   5360   mtp_handler.putfunc = put_func;
   5361   mtp_handler.priv = priv;
   5362 
   5363   PTPDataHandler handler;
   5364   handler.getfunc = NULL;
   5365   handler.putfunc = put_func_wrapper;
   5366   handler.priv = &mtp_handler;
   5367 
   5368   ret = ptp_getobject_to_handler(params, id, &handler);
   5369 
   5370   ptp_usb->callback_active = 0;
   5371   ptp_usb->current_transfer_callback = NULL;
   5372   ptp_usb->current_transfer_callback_data = NULL;
   5373 
   5374   if (ret == PTP_ERROR_CANCEL) {
   5375     add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Get_File_From_File_Descriptor(): Cancelled transfer.");
   5376     return -1;
   5377   }
   5378   if (ret != PTP_RC_OK) {
   5379     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_File_To_File_Descriptor(): Could not get file from device.");
   5380     return -1;
   5381   }
   5382 
   5383   return 0;
   5384 }
   5385 
   5386 
   5387 /**
   5388  * This gets a track off the device to a file identified
   5389  * by a filename. This is actually just a wrapper for the
   5390  * \c LIBMTP_Get_Track_To_File() function.
   5391  * @param device a pointer to the device to get the track from.
   5392  * @param id the track ID of the track to retrieve.
   5393  * @param path a filename to use for the retrieved track.
   5394  * @param callback a progress indicator function or NULL to ignore.
   5395  * @param data a user-defined pointer that is passed along to
   5396  *             the <code>progress</code> function in order to
   5397  *             pass along some user defined data to the progress
   5398  *             updates. If not used, set this to NULL.
   5399  * @return 0 if the transfer was successful, any other value means
   5400  *           failure.
   5401  * @see LIBMTP_Get_Track_To_File_Descriptor()
   5402  */
   5403 int LIBMTP_Get_Track_To_File(LIBMTP_mtpdevice_t *device, uint32_t const id,
   5404 			 char const * const path, LIBMTP_progressfunc_t const callback,
   5405 			 void const * const data)
   5406 {
   5407   // This is just a wrapper
   5408   return LIBMTP_Get_File_To_File(device, id, path, callback, data);
   5409 }
   5410 
   5411 /**
   5412  * This gets a track off the device to a file identified
   5413  * by a file descriptor. This is actually just a wrapper for
   5414  * the \c LIBMTP_Get_File_To_File_Descriptor() function.
   5415  * @param device a pointer to the device to get the track from.
   5416  * @param id the track ID of the track to retrieve.
   5417  * @param fd a file descriptor to write the track to.
   5418  * @param callback a progress indicator function or NULL to ignore.
   5419  * @param data a user-defined pointer that is passed along to
   5420  *             the <code>progress</code> function in order to
   5421  *             pass along some user defined data to the progress
   5422  *             updates. If not used, set this to NULL.
   5423  * @return 0 if the transfer was successful, any other value means
   5424  *           failure.
   5425  * @see LIBMTP_Get_Track_To_File()
   5426  */
   5427 int LIBMTP_Get_Track_To_File_Descriptor(LIBMTP_mtpdevice_t *device,
   5428 					uint32_t const id,
   5429 					int const fd,
   5430 					LIBMTP_progressfunc_t const callback,
   5431 					void const * const data)
   5432 {
   5433   // This is just a wrapper
   5434   return LIBMTP_Get_File_To_File_Descriptor(device, id, fd, callback, data);
   5435 }
   5436 
   5437 /**
   5438  * This gets a track off the device to a handler function.
   5439  * This is actually just a wrapper for
   5440  * the \c LIBMTP_Get_File_To_Handler() function.
   5441  * @param device a pointer to the device to get the track from.
   5442  * @param id the track ID of the track to retrieve.
   5443  * @param put_func the function to call when we have data.
   5444  * @param priv the user-defined pointer that is passed to
   5445  *             <code>put_func</code>.
   5446  * @param callback a progress indicator function or NULL to ignore.
   5447  * @param data a user-defined pointer that is passed along to
   5448  *             the <code>progress</code> function in order to
   5449  *             pass along some user defined data to the progress
   5450  *             updates. If not used, set this to NULL.
   5451  * @return 0 if the transfer was successful, any other value means
   5452  *           failure.
   5453  */
   5454 int LIBMTP_Get_Track_To_Handler(LIBMTP_mtpdevice_t *device,
   5455 					uint32_t const id,
   5456 					MTPDataPutFunc put_func,
   5457           void * priv,
   5458 					LIBMTP_progressfunc_t const callback,
   5459 					void const * const data)
   5460 {
   5461   // This is just a wrapper
   5462   return LIBMTP_Get_File_To_Handler(device, id, put_func, priv, callback, data);
   5463 }
   5464 
   5465 /**
   5466  * This function sends a track from a local file to an
   5467  * MTP device. A filename and a set of metadata must be
   5468  * given as input.
   5469  * @param device a pointer to the device to send the track to.
   5470  * @param path the filename of a local file which will be sent.
   5471  * @param metadata a track metadata set to be written along with the file.
   5472  *        After this call the field <code>metadata-&gt;item_id</code>
   5473  *        will contain the new track ID. Other fields such
   5474  *        as the <code>metadata-&gt;filename</code>, <code>metadata-&gt;parent_id</code>
   5475  *        or <code>metadata-&gt;storage_id</code> may also change during this
   5476  *        operation due to device restrictions, so do not rely on the
   5477  *        contents of this struct to be preserved in any way.
   5478  *        <ul>
   5479  *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
   5480  *        (e.g. folder) to store this track in. Since some
   5481  *        devices are a bit picky about where files
   5482  *        are placed, a default folder will be chosen if libmtp
   5483  *        has detected one for the current filetype and this
   5484  *        parameter is set to 0. If this is 0 and no default folder
   5485  *        can be found, the file will be stored in the root folder.
   5486  *        <li><code>metadata-&gt;storage_id</code> should be set to the
   5487  *        desired storage (e.g. memory card or whatever your device
   5488  *        presents) to store this track in. Setting this to 0 will store
   5489  *        the track on the primary storage.
   5490  *        </ul>
   5491  * @param callback a progress indicator function or NULL to ignore.
   5492  * @param data a user-defined pointer that is passed along to
   5493  *             the <code>progress</code> function in order to
   5494  *             pass along some user defined data to the progress
   5495  *             updates. If not used, set this to NULL.
   5496  * @return 0 if the transfer was successful, any other value means
   5497  *           failure.
   5498  * @see LIBMTP_Send_Track_From_File_Descriptor()
   5499  * @see LIBMTP_Send_File_From_File()
   5500  * @see LIBMTP_Delete_Object()
   5501  */
   5502 int LIBMTP_Send_Track_From_File(LIBMTP_mtpdevice_t *device,
   5503 			 char const * const path, LIBMTP_track_t * const metadata,
   5504                          LIBMTP_progressfunc_t const callback,
   5505 			 void const * const data)
   5506 {
   5507   int fd;
   5508   int ret;
   5509 
   5510   // Sanity check
   5511   if (path == NULL) {
   5512     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_Track_From_File(): Bad arguments, path was NULL.");
   5513     return -1;
   5514   }
   5515 
   5516   // Open file
   5517 #ifdef __WIN32__
   5518 #ifdef USE_WINDOWS_IO_H
   5519   if ( (fd = _open(path, O_RDONLY|O_BINARY)) == -1 ) {
   5520 #else
   5521   if ( (fd = open(path, O_RDONLY|O_BINARY)) == -1 ) {
   5522 #endif
   5523 #else
   5524   if ( (fd = open(path, O_RDONLY)) == -1) {
   5525 #endif
   5526     LIBMTP_ERROR("LIBMTP_Send_Track_From_File(): Could not open source file \"%s\"\n", path);
   5527     return -1;
   5528   }
   5529 
   5530   ret = LIBMTP_Send_Track_From_File_Descriptor(device, fd, metadata, callback, data);
   5531 
   5532   // Close file.
   5533 #ifdef USE_WINDOWS_IO_H
   5534   _close(fd);
   5535 #else
   5536   close(fd);
   5537 #endif
   5538 
   5539   return ret;
   5540 }
   5541 
   5542 
   5543 
   5544 /**
   5545  * This helper function checks if a filename already exists on the device
   5546  * @param PTPParams*
   5547  * @param string representing the filename
   5548  * @return 0 if the filename doesn't exist, -1 if it does
   5549  */
   5550 static int check_filename_exists(PTPParams* params, char const * const filename)
   5551 {
   5552   int i;
   5553 
   5554   for (i = 0; i < params->nrofobjects; i++) {
   5555     char *fname = params->objects[i].oi.Filename;
   5556     if ((fname != NULL) && (strcmp(filename, fname) == 0))
   5557     {
   5558       return -1;
   5559     }
   5560   }
   5561 
   5562   return 0;
   5563 }
   5564 
   5565 /**
   5566  * This helper function returns a unique filename, with a random string before the extension
   5567  * @param string representing the original filename
   5568  * @return a string representing the unique filename
   5569  */
   5570 static char *generate_unique_filename(PTPParams* params, char const * const filename)
   5571 {
   5572   int suffix;
   5573   char * extension_position;
   5574 
   5575   if (check_filename_exists(params, filename))
   5576   {
   5577     extension_position = strrchr(filename,'.');
   5578 
   5579     char basename[extension_position - filename + 1];
   5580     strncpy(basename, filename, extension_position - filename);
   5581     basename[extension_position - filename] = '\0';
   5582 
   5583     suffix = 1;
   5584     char newname[ strlen(basename) + 6 + strlen(extension_position)];
   5585     sprintf(newname, "%s_%d%s", basename, suffix, extension_position);
   5586     while ((check_filename_exists(params, newname)) && (suffix < 1000000)) {
   5587       suffix++;
   5588       sprintf(newname, "%s_%d%s", basename, suffix, extension_position);
   5589     }
   5590   return strdup(newname);
   5591   }
   5592   else
   5593   {
   5594     return strdup(filename);
   5595   }
   5596 }
   5597 
   5598 /**
   5599  * This function sends a track from a file descriptor to an
   5600  * MTP device. A filename and a set of metadata must be
   5601  * given as input.
   5602  * @param device a pointer to the device to send the track to.
   5603  * @param fd the filedescriptor for a local file which will be sent.
   5604  * @param metadata a track metadata set to be written along with the file.
   5605  *        After this call the field <code>metadata-&gt;item_id</code>
   5606  *        will contain the new track ID. Other fields such
   5607  *        as the <code>metadata-&gt;filename</code>, <code>metadata-&gt;parent_id</code>
   5608  *        or <code>metadata-&gt;storage_id</code> may also change during this
   5609  *        operation due to device restrictions, so do not rely on the
   5610  *        contents of this struct to be preserved in any way.
   5611  *        <ul>
   5612  *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
   5613  *        (e.g. folder) to store this track in. Since some
   5614  *        devices are a bit picky about where files
   5615  *        are placed, a default folder will be chosen if libmtp
   5616  *        has detected one for the current filetype and this
   5617  *        parameter is set to 0. If this is 0 and no default folder
   5618  *        can be found, the file will be stored in the root folder.
   5619  *        <li><code>metadata-&gt;storage_id</code> should be set to the
   5620  *        desired storage (e.g. memory card or whatever your device
   5621  *        presents) to store this track in. Setting this to 0 will store
   5622  *        the track on the primary storage.
   5623  *        </ul>
   5624  * @param callback a progress indicator function or NULL to ignore.
   5625  * @param data a user-defined pointer that is passed along to
   5626  *             the <code>progress</code> function in order to
   5627  *             pass along some user defined data to the progress
   5628  *             updates. If not used, set this to NULL.
   5629  * @return 0 if the transfer was successful, any other value means
   5630  *           failure.
   5631  * @see LIBMTP_Send_Track_From_File()
   5632  * @see LIBMTP_Delete_Object()
   5633  */
   5634 int LIBMTP_Send_Track_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
   5635 			 int const fd, LIBMTP_track_t * const metadata,
   5636                          LIBMTP_progressfunc_t const callback,
   5637 			 void const * const data)
   5638 {
   5639   int subcall_ret;
   5640   LIBMTP_file_t filedata;
   5641   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   5642   PTPParams *params = (PTPParams *) device->params;
   5643 
   5644   // Sanity check, is this really a track?
   5645   if (!LIBMTP_FILETYPE_IS_TRACK(metadata->filetype)) {
   5646     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   5647 			    "LIBMTP_Send_Track_From_File_Descriptor(): "
   5648 			    "I don't think this is actually a track, strange filetype...");
   5649   }
   5650 
   5651   // Wrap around the file transfer function
   5652   filedata.item_id = metadata->item_id;
   5653   filedata.parent_id = metadata->parent_id;
   5654   filedata.storage_id = metadata->storage_id;
   5655   if FLAG_UNIQUE_FILENAMES(ptp_usb) {
   5656     filedata.filename = generate_unique_filename(params, metadata->filename);
   5657   }
   5658   else {
   5659     filedata.filename = metadata->filename;
   5660   }
   5661   filedata.filesize = metadata->filesize;
   5662   filedata.filetype = metadata->filetype;
   5663   filedata.next = NULL;
   5664 
   5665   subcall_ret = LIBMTP_Send_File_From_File_Descriptor(device,
   5666 						      fd,
   5667 						      &filedata,
   5668 						      callback,
   5669 						      data);
   5670 
   5671   if (subcall_ret != 0) {
   5672     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   5673 			    "LIBMTP_Send_Track_From_File_Descriptor(): "
   5674 			    "subcall to LIBMTP_Send_File_From_File_Descriptor failed.");
   5675     // We used to delete the file here, but don't... It might be OK after all.
   5676     // (void) LIBMTP_Delete_Object(device, metadata->item_id);
   5677     return -1;
   5678   }
   5679 
   5680   // Pick up new item (and parent, storage) ID
   5681   metadata->item_id = filedata.item_id;
   5682   metadata->parent_id = filedata.parent_id;
   5683   metadata->storage_id = filedata.storage_id;
   5684 
   5685   // Set track metadata for the new fine track
   5686   subcall_ret = LIBMTP_Update_Track_Metadata(device, metadata);
   5687   if (subcall_ret != 0) {
   5688     // Subcall will add error to errorstack
   5689     // We used to delete the file here, but don't... It might be OK after all.
   5690     // (void) LIBMTP_Delete_Object(device, metadata->item_id);
   5691     return -1;
   5692   }
   5693 
   5694   // note we don't need to update the cache here because LIBMTP_Send_File_From_File_Descriptor
   5695   // has added the object handle and LIBMTP_Update_Track_Metadata has added the metadata.
   5696 
   5697   return 0;
   5698 }
   5699 
   5700 /**
   5701  * This function sends a track from a handler function to an
   5702  * MTP device. A filename and a set of metadata must be
   5703  * given as input.
   5704  * @param device a pointer to the device to send the track to.
   5705  * @param get_func the function to call when we have data.
   5706  * @param priv the user-defined pointer that is passed to
   5707  *             <code>get_func</code>.
   5708  * @param metadata a track metadata set to be written along with the file.
   5709  *        After this call the field <code>metadata-&gt;item_id</code>
   5710  *        will contain the new track ID. Other fields such
   5711  *        as the <code>metadata-&gt;filename</code>, <code>metadata-&gt;parent_id</code>
   5712  *        or <code>metadata-&gt;storage_id</code> may also change during this
   5713  *        operation due to device restrictions, so do not rely on the
   5714  *        contents of this struct to be preserved in any way.
   5715  *        <ul>
   5716  *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
   5717  *        (e.g. folder) to store this track in. Since some
   5718  *        devices are a bit picky about where files
   5719  *        are placed, a default folder will be chosen if libmtp
   5720  *        has detected one for the current filetype and this
   5721  *        parameter is set to 0. If this is 0 and no default folder
   5722  *        can be found, the file will be stored in the root folder.
   5723  *        <li><code>metadata-&gt;storage_id</code> should be set to the
   5724  *        desired storage (e.g. memory card or whatever your device
   5725  *        presents) to store this track in. Setting this to 0 will store
   5726  *        the track on the primary storage.
   5727  *        </ul>
   5728  * @param callback a progress indicator function or NULL to ignore.
   5729  * @param data a user-defined pointer that is passed along to
   5730  *             the <code>progress</code> function in order to
   5731  *             pass along some user defined data to the progress
   5732  *             updates. If not used, set this to NULL.
   5733  * @return 0 if the transfer was successful, any other value means
   5734  *           failure.
   5735  * @see LIBMTP_Send_Track_From_File()
   5736  * @see LIBMTP_Delete_Object()
   5737  */
   5738 int LIBMTP_Send_Track_From_Handler(LIBMTP_mtpdevice_t *device,
   5739 			 MTPDataGetFunc get_func, void * priv, LIBMTP_track_t * const metadata,
   5740                          LIBMTP_progressfunc_t const callback,
   5741 			 void const * const data)
   5742 {
   5743   int subcall_ret;
   5744   LIBMTP_file_t filedata;
   5745   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   5746   PTPParams *params = (PTPParams *) device->params;
   5747 
   5748   // Sanity check, is this really a track?
   5749   if (!LIBMTP_FILETYPE_IS_TRACK(metadata->filetype)) {
   5750     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   5751 			    "LIBMTP_Send_Track_From_Handler(): "
   5752 			    "I don't think this is actually a track, strange filetype...");
   5753   }
   5754 
   5755   // Wrap around the file transfer function
   5756   filedata.item_id = metadata->item_id;
   5757   filedata.parent_id = metadata->parent_id;
   5758   filedata.storage_id = metadata->storage_id;
   5759   if FLAG_UNIQUE_FILENAMES(ptp_usb) {
   5760     filedata.filename = generate_unique_filename(params, metadata->filename);
   5761   }
   5762   else {
   5763     filedata.filename = metadata->filename;
   5764   }
   5765   filedata.filesize = metadata->filesize;
   5766   filedata.filetype = metadata->filetype;
   5767   filedata.next = NULL;
   5768 
   5769   subcall_ret = LIBMTP_Send_File_From_Handler(device,
   5770 					      get_func,
   5771 					      priv,
   5772 					      &filedata,
   5773 					      callback,
   5774 					      data);
   5775 
   5776   if (subcall_ret != 0) {
   5777     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   5778 			    "LIBMTP_Send_Track_From_Handler(): "
   5779 			    "subcall to LIBMTP_Send_File_From_Handler failed.");
   5780     // We used to delete the file here, but don't... It might be OK after all.
   5781     // (void) LIBMTP_Delete_Object(device, metadata->item_id);
   5782     return -1;
   5783   }
   5784 
   5785   // Pick up new item (and parent, storage) ID
   5786   metadata->item_id = filedata.item_id;
   5787   metadata->parent_id = filedata.parent_id;
   5788   metadata->storage_id = filedata.storage_id;
   5789 
   5790   // Set track metadata for the new fine track
   5791   subcall_ret = LIBMTP_Update_Track_Metadata(device, metadata);
   5792   if (subcall_ret != 0) {
   5793     // Subcall will add error to errorstack
   5794     // We used to delete the file here, but don't... It might be OK after all.
   5795     // (void) LIBMTP_Delete_Object(device, metadata->item_id);
   5796     return -1;
   5797   }
   5798 
   5799   // note we don't need to update the cache here because LIBMTP_Send_File_From_File_Descriptor
   5800   // has added the object handle and LIBMTP_Update_Track_Metadata has added the metadata.
   5801 
   5802   return 0;
   5803 }
   5804 
   5805 /**
   5806  * This function sends a local file to an MTP device.
   5807  * A filename and a set of metadata must be
   5808  * given as input.
   5809  * @param device a pointer to the device to send the track to.
   5810  * @param path the filename of a local file which will be sent.
   5811  * @param filedata a file metadata set to be written along with the file.
   5812  *        After this call the field <code>filedata-&gt;item_id</code>
   5813  *        will contain the new file ID. Other fields such
   5814  *        as the <code>filedata-&gt;filename</code>, <code>filedata-&gt;parent_id</code>
   5815  *        or <code>filedata-&gt;storage_id</code> may also change during this
   5816  *        operation due to device restrictions, so do not rely on the
   5817  *        contents of this struct to be preserved in any way.
   5818  *        <ul>
   5819  *        <li><code>filedata-&gt;parent_id</code> should be set to the parent
   5820  *        (e.g. folder) to store this file in. If this is 0,
   5821  *        the file will be stored in the root folder.
   5822  *        <li><code>filedata-&gt;storage_id</code> should be set to the
   5823  *        desired storage (e.g. memory card or whatever your device
   5824  *        presents) to store this file in. Setting this to 0 will store
   5825  *        the file on the primary storage.
   5826  *        </ul>
   5827  * @param callback a progress indicator function or NULL to ignore.
   5828  * @param data a user-defined pointer that is passed along to
   5829  *             the <code>progress</code> function in order to
   5830  *             pass along some user defined data to the progress
   5831  *             updates. If not used, set this to NULL.
   5832  * @return 0 if the transfer was successful, any other value means
   5833  *           failure.
   5834  * @see LIBMTP_Send_File_From_File_Descriptor()
   5835  * @see LIBMTP_Delete_Object()
   5836  */
   5837 int LIBMTP_Send_File_From_File(LIBMTP_mtpdevice_t *device,
   5838 			       char const * const path, LIBMTP_file_t * const filedata,
   5839 			       LIBMTP_progressfunc_t const callback,
   5840 			       void const * const data)
   5841 {
   5842   int fd;
   5843   int ret;
   5844 
   5845   // Sanity check
   5846   if (path == NULL) {
   5847     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_File_From_File(): Bad arguments, path was NULL.");
   5848     return -1;
   5849   }
   5850 
   5851   // Open file
   5852 #ifdef __WIN32__
   5853 #ifdef USE_WINDOWS_IO_H
   5854   if ( (fd = _open(path, O_RDONLY|O_BINARY)) == -1 ) {
   5855 #else
   5856   if ( (fd = open(path, O_RDONLY|O_BINARY)) == -1 ) {
   5857 #endif
   5858 #else
   5859   if ( (fd = open(path, O_RDONLY)) == -1) {
   5860 #endif
   5861     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_File_From_File(): Could not open source file.");
   5862     return -1;
   5863   }
   5864 
   5865   ret = LIBMTP_Send_File_From_File_Descriptor(device, fd, filedata, callback, data);
   5866 
   5867   // Close file.
   5868 #ifdef USE_WINDOWS_IO_H
   5869   _close(fd);
   5870 #else
   5871   close(fd);
   5872 #endif
   5873 
   5874   return ret;
   5875 }
   5876 
   5877 /**
   5878  * This function sends a generic file from a file descriptor to an
   5879  * MTP device. A filename and a set of metadata must be
   5880  * given as input.
   5881  *
   5882  * This can potentially be used for sending in a stream of unknown
   5883  * length. Send music files with
   5884  * <code>LIBMTP_Send_Track_From_File_Descriptor()</code>
   5885  *
   5886  * @param device a pointer to the device to send the file to.
   5887  * @param fd the filedescriptor for a local file which will be sent.
   5888  * @param filedata a file metadata set to be written along with the file.
   5889  *        After this call the field <code>filedata-&gt;item_id</code>
   5890  *        will contain the new file ID. Other fields such
   5891  *        as the <code>filedata-&gt;filename</code>, <code>filedata-&gt;parent_id</code>
   5892  *        or <code>filedata-&gt;storage_id</code> may also change during this
   5893  *        operation due to device restrictions, so do not rely on the
   5894  *        contents of this struct to be preserved in any way.
   5895  *        <ul>
   5896  *        <li><code>filedata-&gt;parent_id</code> should be set to the parent
   5897  *        (e.g. folder) to store this file in. If this is 0,
   5898  *        the file will be stored in the root folder.
   5899  *        <li><code>filedata-&gt;storage_id</code> should be set to the
   5900  *        desired storage (e.g. memory card or whatever your device
   5901  *        presents) to store this file in. Setting this to 0 will store
   5902  *        the file on the primary storage.
   5903  *        </ul>
   5904  * @param callback a progress indicator function or NULL to ignore.
   5905  * @param data a user-defined pointer that is passed along to
   5906  *             the <code>progress</code> function in order to
   5907  *             pass along some user defined data to the progress
   5908  *             updates. If not used, set this to NULL.
   5909  * @return 0 if the transfer was successful, any other value means
   5910  *           failure.
   5911  * @see LIBMTP_Send_File_From_File()
   5912  * @see LIBMTP_Send_Track_From_File_Descriptor()
   5913  * @see LIBMTP_Delete_Object()
   5914  */
   5915 int LIBMTP_Send_File_From_File_Descriptor(LIBMTP_mtpdevice_t *device,
   5916 			 int const fd, LIBMTP_file_t * const filedata,
   5917                          LIBMTP_progressfunc_t const callback,
   5918 			 void const * const data)
   5919 {
   5920   uint16_t ret;
   5921   PTPParams *params = (PTPParams *) device->params;
   5922   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   5923   LIBMTP_file_t *newfilemeta;
   5924   int oldtimeout;
   5925   int timeout;
   5926 
   5927   if (send_file_object_info(device, filedata))
   5928   {
   5929     // no need to output an error since send_file_object_info will already have done so
   5930     return -1;
   5931   }
   5932 
   5933   // Callbacks
   5934   ptp_usb->callback_active = 1;
   5935   // The callback will deactivate itself after this amount of data has been sent
   5936   // One BULK header for the request, one for the data phase. No parameters to the request.
   5937   ptp_usb->current_transfer_total = filedata->filesize+PTP_USB_BULK_HDR_LEN*2;
   5938   ptp_usb->current_transfer_complete = 0;
   5939   ptp_usb->current_transfer_callback = callback;
   5940   ptp_usb->current_transfer_callback_data = data;
   5941 
   5942   /*
   5943    * We might need to increase the timeout here, files can be pretty
   5944    * large. Take the default timeout and add the calculated time for
   5945    * this transfer
   5946    */
   5947   get_usb_device_timeout(ptp_usb, &oldtimeout);
   5948   timeout = oldtimeout +
   5949     (ptp_usb->current_transfer_total / guess_usb_speed(ptp_usb)) * 1000;
   5950   set_usb_device_timeout(ptp_usb, timeout);
   5951 
   5952   ret = ptp_sendobject_fromfd(params, fd, filedata->filesize);
   5953 
   5954   ptp_usb->callback_active = 0;
   5955   ptp_usb->current_transfer_callback = NULL;
   5956   ptp_usb->current_transfer_callback_data = NULL;
   5957   set_usb_device_timeout(ptp_usb, oldtimeout);
   5958 
   5959   if (ret == PTP_ERROR_CANCEL) {
   5960     add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Send_File_From_File_Descriptor(): Cancelled transfer.");
   5961     return -1;
   5962   }
   5963   if (ret != PTP_RC_OK) {
   5964     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_File_From_File_Descriptor(): "
   5965 				"Could not send object.");
   5966     return -1;
   5967   }
   5968 
   5969   add_object_to_cache(device, filedata->item_id);
   5970 
   5971   /*
   5972    * Get the device-assigned parent_id from the cache.
   5973    * The operation that adds it to the cache will
   5974    * look it up from the device, so we get the new
   5975    * parent_id from the cache.
   5976    */
   5977   newfilemeta = LIBMTP_Get_Filemetadata(device, filedata->item_id);
   5978   if (newfilemeta != NULL) {
   5979     filedata->parent_id = newfilemeta->parent_id;
   5980     filedata->storage_id = newfilemeta->storage_id;
   5981     LIBMTP_destroy_file_t(newfilemeta);
   5982   } else {
   5983     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   5984 			    "LIBMTP_Send_File_From_File_Descriptor(): "
   5985 			    "Could not retrieve updated metadata.");
   5986     return -1;
   5987   }
   5988 
   5989   return 0;
   5990 }
   5991 
   5992 /**
   5993  * This function sends a generic file from a handler function to an
   5994  * MTP device. A filename and a set of metadata must be
   5995  * given as input.
   5996  *
   5997  * This can potentially be used for sending in a stream of unknown
   5998  * length. Send music files with
   5999  * <code>LIBMTP_Send_Track_From_Handler()</code>
   6000  *
   6001  * @param device a pointer to the device to send the file to.
   6002  * @param get_func the function to call to get data to write
   6003  * @param priv a user-defined pointer that is passed along to
   6004  *        <code>get_func</code>. If not used, this is set to NULL.
   6005  * @param filedata a file metadata set to be written along with the file.
   6006  *        After this call the field <code>filedata-&gt;item_id</code>
   6007  *        will contain the new file ID. Other fields such
   6008  *        as the <code>filedata-&gt;filename</code>, <code>filedata-&gt;parent_id</code>
   6009  *        or <code>filedata-&gt;storage_id</code> may also change during this
   6010  *        operation due to device restrictions, so do not rely on the
   6011  *        contents of this struct to be preserved in any way.
   6012  *        <ul>
   6013  *        <li><code>filedata-&gt;parent_id</code> should be set to the parent
   6014  *        (e.g. folder) to store this file in. If this is 0,
   6015  *        the file will be stored in the root folder.
   6016  *        <li><code>filedata-&gt;storage_id</code> should be set to the
   6017  *        desired storage (e.g. memory card or whatever your device
   6018  *        presents) to store this file in. Setting this to 0 will store
   6019  *        the file on the primary storage.
   6020  *        </ul>
   6021  * @param callback a progress indicator function or NULL to ignore.
   6022  * @param data a user-defined pointer that is passed along to
   6023  *             the <code>progress</code> function in order to
   6024  *             pass along some user defined data to the progress
   6025  *             updates. If not used, set this to NULL.
   6026  * @return 0 if the transfer was successful, any other value means
   6027  *           failure.
   6028  * @see LIBMTP_Send_File_From_File()
   6029  * @see LIBMTP_Send_Track_From_File_Descriptor()
   6030  * @see LIBMTP_Delete_Object()
   6031  */
   6032 int LIBMTP_Send_File_From_Handler(LIBMTP_mtpdevice_t *device,
   6033 			 MTPDataGetFunc get_func, void * priv, LIBMTP_file_t * const filedata,
   6034        LIBMTP_progressfunc_t const callback, void const * const data)
   6035 {
   6036   uint16_t ret;
   6037   PTPParams *params = (PTPParams *) device->params;
   6038   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   6039   LIBMTP_file_t *newfilemeta;
   6040 
   6041   if (send_file_object_info(device, filedata))
   6042   {
   6043     // no need to output an error since send_file_object_info will already have done so
   6044     return -1;
   6045   }
   6046 
   6047   // Callbacks
   6048   ptp_usb->callback_active = 1;
   6049   // The callback will deactivate itself after this amount of data has been sent
   6050   // One BULK header for the request, one for the data phase. No parameters to the request.
   6051   ptp_usb->current_transfer_total = filedata->filesize+PTP_USB_BULK_HDR_LEN*2;
   6052   ptp_usb->current_transfer_complete = 0;
   6053   ptp_usb->current_transfer_callback = callback;
   6054   ptp_usb->current_transfer_callback_data = data;
   6055 
   6056   MTPDataHandler mtp_handler;
   6057   mtp_handler.getfunc = get_func;
   6058   mtp_handler.putfunc = NULL;
   6059   mtp_handler.priv = priv;
   6060 
   6061   PTPDataHandler handler;
   6062   handler.getfunc = get_func_wrapper;
   6063   handler.putfunc = NULL;
   6064   handler.priv = &mtp_handler;
   6065 
   6066   ret = ptp_sendobject_from_handler(params, &handler, filedata->filesize);
   6067 
   6068   ptp_usb->callback_active = 0;
   6069   ptp_usb->current_transfer_callback = NULL;
   6070   ptp_usb->current_transfer_callback_data = NULL;
   6071 
   6072   if (ret == PTP_ERROR_CANCEL) {
   6073     add_error_to_errorstack(device, LIBMTP_ERROR_CANCELLED, "LIBMTP_Send_File_From_Handler(): Cancelled transfer.");
   6074     return -1;
   6075   }
   6076   if (ret != PTP_RC_OK) {
   6077     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_File_From_Handler(): "
   6078 				"Could not send object.");
   6079     return -1;
   6080   }
   6081 
   6082   add_object_to_cache(device, filedata->item_id);
   6083 
   6084   /*
   6085    * Get the device-assined parent_id from the cache.
   6086    * The operation that adds it to the cache will
   6087    * look it up from the device, so we get the new
   6088    * parent_id from the cache.
   6089    */
   6090   newfilemeta = LIBMTP_Get_Filemetadata(device, filedata->item_id);
   6091   if (newfilemeta != NULL) {
   6092     filedata->parent_id = newfilemeta->parent_id;
   6093     filedata->storage_id = newfilemeta->storage_id;
   6094     LIBMTP_destroy_file_t(newfilemeta);
   6095   } else {
   6096     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   6097 			    "LIBMTP_Send_File_From_Handler(): "
   6098 			    "Could not retrieve updated metadata.");
   6099     return -1;
   6100   }
   6101 
   6102   return 0;
   6103 }
   6104 
   6105 /**
   6106  * This function sends the file object info, ready for sendobject
   6107  * @param device a pointer to the device to send the file to.
   6108  * @param filedata a file metadata set to be written along with the file.
   6109  * @return 0 if the transfer was successful, any other value means
   6110  *           failure.
   6111  */
   6112 static int send_file_object_info(LIBMTP_mtpdevice_t *device, LIBMTP_file_t *filedata)
   6113 {
   6114   PTPParams *params = (PTPParams *) device->params;
   6115   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   6116   uint32_t store;
   6117   int use_primary_storage = 1;
   6118   uint16_t of = map_libmtp_type_to_ptp_type(filedata->filetype);
   6119   LIBMTP_devicestorage_t *storage;
   6120   uint32_t localph = filedata->parent_id;
   6121   uint16_t ret;
   6122   int i;
   6123 
   6124 #if 0
   6125   // Sanity check: no zerolength files on some devices?
   6126   // If the zerolength files cause problems on some devices,
   6127   // then add a bug flag for this.
   6128   if (filedata->filesize == 0) {
   6129     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "send_file_object_info(): "
   6130 			    "File of zero size.");
   6131     return -1;
   6132   }
   6133 #endif
   6134   if (filedata->storage_id != 0) {
   6135     store = filedata->storage_id;
   6136   } else {
   6137     store = get_suggested_storage_id(device, filedata->filesize, localph);
   6138   }
   6139 
   6140   // Detect if something non-primary is in use.
   6141   storage = device->storage;
   6142   if (storage != NULL && store != storage->id) {
   6143     use_primary_storage = 0;
   6144   }
   6145 
   6146   /*
   6147    * If no destination folder was given, look up a default
   6148    * folder if possible. Perhaps there is some way of retrieveing
   6149    * the default folder for different forms of content, what
   6150    * do I know, we use a fixed list in lack of any better method.
   6151    * Some devices obviously need to have their files in certain
   6152    * folders in order to find/display them at all (hello Creative),
   6153    * so we have to have a method for this. We only do this if the
   6154    * primary storage is in use.
   6155    */
   6156 
   6157   if (localph == 0 && use_primary_storage) {
   6158     if (LIBMTP_FILETYPE_IS_AUDIO(filedata->filetype)) {
   6159       localph = device->default_music_folder;
   6160     } else if (LIBMTP_FILETYPE_IS_VIDEO(filedata->filetype)) {
   6161       localph = device->default_video_folder;
   6162     } else if (of == PTP_OFC_EXIF_JPEG ||
   6163 	       of == PTP_OFC_JP2 ||
   6164 	       of == PTP_OFC_JPX ||
   6165 	       of == PTP_OFC_JFIF ||
   6166 	       of == PTP_OFC_TIFF ||
   6167 	       of == PTP_OFC_TIFF_IT ||
   6168 	       of == PTP_OFC_BMP ||
   6169 	       of == PTP_OFC_GIF ||
   6170 	       of == PTP_OFC_PICT ||
   6171 	       of == PTP_OFC_PNG ||
   6172 	       of == PTP_OFC_MTP_WindowsImageFormat) {
   6173       localph = device->default_picture_folder;
   6174     } else if (of == PTP_OFC_MTP_vCalendar1 ||
   6175 	       of == PTP_OFC_MTP_vCalendar2 ||
   6176 	       of == PTP_OFC_MTP_UndefinedContact ||
   6177 	       of == PTP_OFC_MTP_vCard2 ||
   6178 	       of == PTP_OFC_MTP_vCard3 ||
   6179 	       of == PTP_OFC_MTP_UndefinedCalendarItem) {
   6180       localph = device->default_organizer_folder;
   6181     } else if (of == PTP_OFC_Text) {
   6182       localph = device->default_text_folder;
   6183     }
   6184   }
   6185 
   6186   // Here we wire the type to unknown on bugged, but
   6187   // Ogg or FLAC-supportive devices.
   6188   if (FLAG_OGG_IS_UNKNOWN(ptp_usb) && of == PTP_OFC_MTP_OGG) {
   6189     of = PTP_OFC_Undefined;
   6190   }
   6191   if (FLAG_FLAC_IS_UNKNOWN(ptp_usb) && of == PTP_OFC_MTP_FLAC) {
   6192     of = PTP_OFC_Undefined;
   6193   }
   6194 
   6195   if (ptp_operation_issupported(params, PTP_OC_MTP_SendObjectPropList) &&
   6196       !FLAG_BROKEN_SEND_OBJECT_PROPLIST(ptp_usb)) {
   6197     /*
   6198      * MTP enhanched does it this way (from a sniff):
   6199      * -> PTP_OC_MTP_SendObjectPropList (0x9808):
   6200      *    20 00 00 00 01 00 08 98 1B 00 00 00 01 00 01 00
   6201      *    FF FF FF FF 00 30 00 00 00 00 00 00 12 5E 00 00
   6202      *    Length: 0x00000020
   6203      *    Type:   0x0001 PTP_USB_CONTAINER_COMMAND
   6204      *    Code:   0x9808
   6205      *    Transaction ID: 0x0000001B
   6206      *    Param1: 0x00010001 <- store
   6207      *    Param2: 0xffffffff <- parent handle (-1 ?)
   6208      *    Param3: 0x00003000 <- file type PTP_OFC_Undefined - we don't know about PDF files
   6209      *    Param4: 0x00000000 <- file length MSB (-0x0c header len)
   6210      *    Param5: 0x00005e12 <- file length LSB (-0x0c header len)
   6211      *
   6212      * -> PTP_OC_MTP_SendObjectPropList (0x9808):
   6213      *    46 00 00 00 02 00 08 98 1B 00 00 00 03 00 00 00
   6214      *    00 00 00 00 07 DC FF FF 0D 4B 00 53 00 30 00 36 - dc07 = file name
   6215      *    00 30 00 33 00 30 00 36 00 2E 00 70 00 64 00 66
   6216      *    00 00 00 00 00 00 00 03 DC 04 00 00 00 00 00 00 - dc03 = protection status
   6217      *    00 4F DC 02 00 01                               - dc4f = non consumable
   6218      *    Length: 0x00000046
   6219      *    Type:   0x0002 PTP_USB_CONTAINER_DATA
   6220      *    Code:   0x9808
   6221      *    Transaction ID: 0x0000001B
   6222      *    Metadata....
   6223      *    0x00000003 <- Number of metadata items
   6224      *    0x00000000 <- Object handle, set to 0x00000000 since it is unknown!
   6225      *    0xdc07     <- metadata type: file name
   6226      *    0xffff     <- metadata type: string
   6227      *    0x0d       <- number of (uint16_t) characters
   6228      *    4b 53 30 36 30 33 30 36 2e 50 64 66 00 "KS060306.pdf", null terminated
   6229      *    0x00000000 <- Object handle, set to 0x00000000 since it is unknown!
   6230      *    0xdc03     <- metadata type: protection status
   6231      *    0x0004     <- metadata type: uint16_t
   6232      *    0x0000     <- not protected
   6233      *    0x00000000 <- Object handle, set to 0x00000000 since it is unknown!
   6234      *    0xdc4f     <- non consumable
   6235      *    0x0002     <- metadata type: uint8_t
   6236      *    0x01       <- non-consumable (this device cannot display PDF)
   6237      *
   6238      * <- Read 0x18 bytes back
   6239      *    18 00 00 00 03 00 01 20 1B 00 00 00 01 00 01 00
   6240      *    00 00 00 00 01 40 00 00
   6241      *    Length: 0x000000018
   6242      *    Type:   0x0003 PTP_USB_CONTAINER_RESPONSE
   6243      *    Code:   0x2001 PTP_OK
   6244      *    Transaction ID: 0x0000001B
   6245      *    Param1: 0x00010001 <- store
   6246      *    Param2: 0x00000000 <- parent handle
   6247      *    Param3: 0x00004001 <- new file/object ID
   6248      *
   6249      * -> PTP_OC_SendObject (0x100d)
   6250      *    0C 00 00 00 01 00 0D 10 1C 00 00 00
   6251      * -> ... all the bytes ...
   6252      * <- Read 0x0c bytes back
   6253      *    0C 00 00 00 03 00 01 20 1C 00 00 00
   6254      *    ... Then update metadata one-by one, actually (instead of sending it first!) ...
   6255      */
   6256     MTPProperties *props = NULL;
   6257     int nrofprops = 0;
   6258     MTPProperties *prop = NULL;
   6259     uint16_t *properties = NULL;
   6260     uint32_t propcnt = 0;
   6261 
   6262     // default parent handle
   6263     if (localph == 0)
   6264       localph = 0xFFFFFFFFU; // Set to -1
   6265 
   6266     // Must be 0x00000000U for new objects
   6267     filedata->item_id = 0x00000000U;
   6268 
   6269     ret = ptp_mtp_getobjectpropssupported(params, of, &propcnt, &properties);
   6270 
   6271     for (i=0;i<propcnt;i++) {
   6272       PTPObjectPropDesc opd;
   6273 
   6274       ret = ptp_mtp_getobjectpropdesc(params, properties[i], of, &opd);
   6275       if (ret != PTP_RC_OK) {
   6276 	add_ptp_error_to_errorstack(device, ret, "send_file_object_info(): "
   6277 				"could not get property description.");
   6278       } else if (opd.GetSet) {
   6279 	switch (properties[i]) {
   6280 	case PTP_OPC_ObjectFileName:
   6281 	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   6282 	  prop->ObjectHandle = filedata->item_id;
   6283 	  prop->property = PTP_OPC_ObjectFileName;
   6284 	  prop->datatype = PTP_DTC_STR;
   6285 	  if (filedata->filename != NULL) {
   6286 	    prop->propval.str = strdup(filedata->filename);
   6287 	    if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
   6288 	      strip_7bit_from_utf8(prop->propval.str);
   6289 	    }
   6290 	  }
   6291 	  break;
   6292 	case PTP_OPC_ProtectionStatus:
   6293 	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   6294 	  prop->ObjectHandle = filedata->item_id;
   6295 	  prop->property = PTP_OPC_ProtectionStatus;
   6296 	  prop->datatype = PTP_DTC_UINT16;
   6297 	  prop->propval.u16 = 0x0000U; /* Not protected */
   6298 	  break;
   6299 	case PTP_OPC_NonConsumable:
   6300 	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   6301 	  prop->ObjectHandle = filedata->item_id;
   6302 	  prop->property = PTP_OPC_NonConsumable;
   6303 	  prop->datatype = PTP_DTC_UINT8;
   6304 	  prop->propval.u8 = 0x00; /* It is supported, then it is consumable */
   6305 	  break;
   6306 	case PTP_OPC_Name:
   6307 	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   6308 	  prop->ObjectHandle = filedata->item_id;
   6309 	  prop->property = PTP_OPC_Name;
   6310 	  prop->datatype = PTP_DTC_STR;
   6311 	  if (filedata->filename != NULL)
   6312 	    prop->propval.str = strdup(filedata->filename);
   6313 	  break;
   6314 	case PTP_OPC_DateModified:
   6315 	  // Tag with current time if that is supported
   6316 	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
   6317 	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   6318 	    prop->ObjectHandle = filedata->item_id;
   6319 	    prop->property = PTP_OPC_DateModified;
   6320 	    prop->datatype = PTP_DTC_STR;
   6321 	    prop->propval.str = get_iso8601_stamp();
   6322 	    filedata->modificationdate = time(NULL);
   6323 	  }
   6324 	  break;
   6325 	}
   6326       }
   6327       ptp_free_objectpropdesc(&opd);
   6328     }
   6329     free(properties);
   6330 
   6331     ret = ptp_mtp_sendobjectproplist(params, &store, &localph, &filedata->item_id,
   6332 				     of, filedata->filesize, props, nrofprops);
   6333 
   6334     /* Free property list */
   6335     ptp_destroy_object_prop_list(props, nrofprops);
   6336 
   6337     if (ret != PTP_RC_OK) {
   6338       add_ptp_error_to_errorstack(device, ret, "send_file_object_info():"
   6339 				  "Could not send object property list.");
   6340       if (ret == PTP_RC_AccessDenied) {
   6341 	add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
   6342       }
   6343       return -1;
   6344     }
   6345   } else if (ptp_operation_issupported(params,PTP_OC_SendObjectInfo)) {
   6346     PTPObjectInfo new_file;
   6347 
   6348     memset(&new_file, 0, sizeof(PTPObjectInfo));
   6349 
   6350     new_file.Filename = filedata->filename;
   6351     if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
   6352       strip_7bit_from_utf8(new_file.Filename);
   6353     }
   6354     if (filedata->filesize > 0xFFFFFFFFL) {
   6355       // This is a kludge in the MTP standard for large files.
   6356       new_file.ObjectCompressedSize = (uint32_t) 0xFFFFFFFF;
   6357     } else {
   6358       new_file.ObjectCompressedSize = (uint32_t) filedata->filesize;
   6359     }
   6360     new_file.ObjectFormat = of;
   6361     new_file.StorageID = store;
   6362     new_file.ParentObject = localph;
   6363     new_file.ModificationDate = time(NULL);
   6364 
   6365     // Create the object
   6366     ret = ptp_sendobjectinfo(params, &store, &localph, &filedata->item_id, &new_file);
   6367 
   6368     if (ret != PTP_RC_OK) {
   6369       add_ptp_error_to_errorstack(device, ret, "send_file_object_info(): "
   6370 				  "Could not send object info.");
   6371       if (ret == PTP_RC_AccessDenied) {
   6372 	add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
   6373       }
   6374       return -1;
   6375     }
   6376     // NOTE: the char* pointers inside new_file are not copies so don't
   6377     // try to destroy this objectinfo!
   6378   }
   6379 
   6380   // Now there IS an object with this parent handle.
   6381   filedata->parent_id = localph;
   6382 
   6383   return 0;
   6384 }
   6385 
   6386 /**
   6387  * This function updates the MTP track object metadata on a
   6388  * single file identified by an object ID.
   6389  * @param device a pointer to the device to update the track
   6390  *        metadata on.
   6391  * @param metadata a track metadata set to be written to the file.
   6392  *        notice that the <code>track_id</code> field of the
   6393  *        metadata structure must be correct so that the
   6394  *        function can update the right file. If some properties
   6395  *        of this metadata are set to NULL (strings) or 0
   6396  *        (numerical values) they will be discarded and the
   6397  *        track will not be tagged with these blank values.
   6398  * @return 0 on success, any other value means failure. If some
   6399  *        or all of the properties fail to update we will still
   6400  *        return success. On some devices (notably iRiver T30)
   6401  *        properties that exist cannot be updated.
   6402  */
   6403 int LIBMTP_Update_Track_Metadata(LIBMTP_mtpdevice_t *device,
   6404 				 LIBMTP_track_t const * const metadata)
   6405 {
   6406   uint16_t ret;
   6407   PTPParams *params = (PTPParams *) device->params;
   6408   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   6409   uint32_t i;
   6410   uint16_t *properties = NULL;
   6411   uint32_t propcnt = 0;
   6412 
   6413   // First see which properties can be set on this file format and apply accordingly
   6414   // i.e only try to update this metadata for object tags that exist on the current player.
   6415   ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(metadata->filetype), &propcnt, &properties);
   6416   if (ret != PTP_RC_OK) {
   6417     // Just bail out for now, nothing is ever set.
   6418     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6419 			    "could not retrieve supported object properties.");
   6420     return -1;
   6421   }
   6422   if (ptp_operation_issupported(params, PTP_OC_MTP_SetObjPropList) &&
   6423       !FLAG_BROKEN_SET_OBJECT_PROPLIST(ptp_usb)) {
   6424     MTPProperties *props = NULL;
   6425     MTPProperties *prop = NULL;
   6426     int nrofprops = 0;
   6427 
   6428     for (i=0;i<propcnt;i++) {
   6429       PTPObjectPropDesc opd;
   6430 
   6431       ret = ptp_mtp_getobjectpropdesc(params, properties[i], map_libmtp_type_to_ptp_type(metadata->filetype), &opd);
   6432       if (ret != PTP_RC_OK) {
   6433 	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6434 				"could not get property description.");
   6435       } else if (opd.GetSet) {
   6436 	switch (properties[i]) {
   6437 	case PTP_OPC_Name:
   6438 	  if (metadata->title == NULL)
   6439 	    break;
   6440 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6441 	  prop->ObjectHandle = metadata->item_id;
   6442 	  prop->property = PTP_OPC_Name;
   6443 	  prop->datatype = PTP_DTC_STR;
   6444 	  prop->propval.str = strdup(metadata->title);
   6445 	  break;
   6446 	case PTP_OPC_AlbumName:
   6447 	  if (metadata->album == NULL)
   6448 	    break;
   6449 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6450 	  prop->ObjectHandle = metadata->item_id;
   6451 	  prop->property = PTP_OPC_AlbumName;
   6452 	  prop->datatype = PTP_DTC_STR;
   6453 	  prop->propval.str = strdup(metadata->album);
   6454 	  break;
   6455 	case PTP_OPC_Artist:
   6456 	  if (metadata->artist == NULL)
   6457 	    break;
   6458 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6459 	  prop->ObjectHandle = metadata->item_id;
   6460 	  prop->property = PTP_OPC_Artist;
   6461 	  prop->datatype = PTP_DTC_STR;
   6462 	  prop->propval.str = strdup(metadata->artist);
   6463 	  break;
   6464 	case PTP_OPC_Composer:
   6465 	  if (metadata->composer == NULL)
   6466 	    break;
   6467 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6468 	  prop->ObjectHandle = metadata->item_id;
   6469 	  prop->property = PTP_OPC_Composer;
   6470 	  prop->datatype = PTP_DTC_STR;
   6471 	  prop->propval.str = strdup(metadata->composer);
   6472 	  break;
   6473 	case PTP_OPC_Genre:
   6474 	  if (metadata->genre == NULL)
   6475 	    break;
   6476 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6477 	  prop->ObjectHandle = metadata->item_id;
   6478 	  prop->property = PTP_OPC_Genre;
   6479 	  prop->datatype = PTP_DTC_STR;
   6480 	  prop->propval.str = strdup(metadata->genre);
   6481 	  break;
   6482 	case PTP_OPC_Duration:
   6483 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6484 	  prop->ObjectHandle = metadata->item_id;
   6485 	  prop->property = PTP_OPC_Duration;
   6486 	  prop->datatype = PTP_DTC_UINT32;
   6487 	  prop->propval.u32 = adjust_u32(metadata->duration, &opd);
   6488 	  break;
   6489 	case PTP_OPC_Track:
   6490 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6491 	  prop->ObjectHandle = metadata->item_id;
   6492 	  prop->property = PTP_OPC_Track;
   6493 	  prop->datatype = PTP_DTC_UINT16;
   6494 	  prop->propval.u16 = adjust_u16(metadata->tracknumber, &opd);
   6495 	  break;
   6496 	case PTP_OPC_OriginalReleaseDate:
   6497 	  if (metadata->date == NULL)
   6498 	    break;
   6499 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6500 	  prop->ObjectHandle = metadata->item_id;
   6501 	  prop->property = PTP_OPC_OriginalReleaseDate;
   6502 	  prop->datatype = PTP_DTC_STR;
   6503 	  prop->propval.str = strdup(metadata->date);
   6504 	  break;
   6505 	case PTP_OPC_SampleRate:
   6506 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6507 	  prop->ObjectHandle = metadata->item_id;
   6508 	  prop->property = PTP_OPC_SampleRate;
   6509 	  prop->datatype = PTP_DTC_UINT32;
   6510 	  prop->propval.u32 = adjust_u32(metadata->samplerate, &opd);
   6511 	  break;
   6512 	case PTP_OPC_NumberOfChannels:
   6513 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6514 	  prop->ObjectHandle = metadata->item_id;
   6515 	  prop->property = PTP_OPC_NumberOfChannels;
   6516 	  prop->datatype = PTP_DTC_UINT16;
   6517 	  prop->propval.u16 = adjust_u16(metadata->nochannels, &opd);
   6518 	  break;
   6519 	case PTP_OPC_AudioWAVECodec:
   6520 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6521 	  prop->ObjectHandle = metadata->item_id;
   6522 	  prop->property = PTP_OPC_AudioWAVECodec;
   6523 	  prop->datatype = PTP_DTC_UINT32;
   6524 	  prop->propval.u32 = adjust_u32(metadata->wavecodec, &opd);
   6525 	  break;
   6526 	case PTP_OPC_AudioBitRate:
   6527 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6528 	  prop->ObjectHandle = metadata->item_id;
   6529 	  prop->property = PTP_OPC_AudioBitRate;
   6530 	  prop->datatype = PTP_DTC_UINT32;
   6531 	  prop->propval.u32 = adjust_u32(metadata->bitrate, &opd);
   6532 	  break;
   6533 	case PTP_OPC_BitRateType:
   6534 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6535 	  prop->ObjectHandle = metadata->item_id;
   6536 	  prop->property = PTP_OPC_BitRateType;
   6537 	  prop->datatype = PTP_DTC_UINT16;
   6538 	  prop->propval.u16 = adjust_u16(metadata->bitratetype, &opd);
   6539 	  break;
   6540 	case PTP_OPC_Rating:
   6541 	  // TODO: shall this be set for rating 0?
   6542 	  if (metadata->rating == 0)
   6543 	    break;
   6544 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6545 	  prop->ObjectHandle = metadata->item_id;
   6546 	  prop->property = PTP_OPC_Rating;
   6547 	  prop->datatype = PTP_DTC_UINT16;
   6548 	  prop->propval.u16 = adjust_u16(metadata->rating, &opd);
   6549 	  break;
   6550 	case PTP_OPC_UseCount:
   6551 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6552 	  prop->ObjectHandle = metadata->item_id;
   6553 	  prop->property = PTP_OPC_UseCount;
   6554 	  prop->datatype = PTP_DTC_UINT32;
   6555 	  prop->propval.u32 = adjust_u32(metadata->usecount, &opd);
   6556 	  break;
   6557 	case PTP_OPC_DateModified:
   6558 	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
   6559 	    // Tag with current time if that is supported
   6560 	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6561 	    prop->ObjectHandle = metadata->item_id;
   6562 	    prop->property = PTP_OPC_DateModified;
   6563 	    prop->datatype = PTP_DTC_STR;
   6564 	    prop->propval.str = get_iso8601_stamp();
   6565 	  }
   6566 	  break;
   6567 	default:
   6568 	  break;
   6569 	}
   6570       }
   6571       ptp_free_objectpropdesc(&opd);
   6572     }
   6573 
   6574     // NOTE: File size is not updated, this should not change anyway.
   6575     // neither will we change the filename.
   6576 
   6577     ret = ptp_mtp_setobjectproplist(params, props, nrofprops);
   6578 
   6579     ptp_destroy_object_prop_list(props, nrofprops);
   6580 
   6581     if (ret != PTP_RC_OK) {
   6582       // TODO: return error of which property we couldn't set
   6583       add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6584 			      "could not set object property list.");
   6585       free(properties);
   6586       return -1;
   6587     }
   6588 
   6589   } else if (ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
   6590     for (i=0;i<propcnt;i++) {
   6591       PTPObjectPropDesc opd;
   6592 
   6593       ret = ptp_mtp_getobjectpropdesc(params, properties[i], map_libmtp_type_to_ptp_type(metadata->filetype), &opd);
   6594       if (ret != PTP_RC_OK) {
   6595 	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6596 				"could not get property description.");
   6597       } else if (opd.GetSet) {
   6598 	switch (properties[i]) {
   6599 	case PTP_OPC_Name:
   6600 	  // Update title
   6601 	  ret = set_object_string(device, metadata->item_id, PTP_OPC_Name, metadata->title);
   6602 	  if (ret != 0) {
   6603 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6604 				    "could not set track title.");
   6605 	  }
   6606 	  break;
   6607 	case PTP_OPC_AlbumName:
   6608 	  // Update album
   6609 	  ret = set_object_string(device, metadata->item_id, PTP_OPC_AlbumName, metadata->album);
   6610 	  if (ret != 0) {
   6611 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6612 				    "could not set track album name.");
   6613 	  }
   6614 	  break;
   6615 	case PTP_OPC_Artist:
   6616 	  // Update artist
   6617 	  ret = set_object_string(device, metadata->item_id, PTP_OPC_Artist, metadata->artist);
   6618 	  if (ret != 0) {
   6619 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6620 				    "could not set track artist name.");
   6621 	  }
   6622 	  break;
   6623 	case PTP_OPC_Composer:
   6624 	  // Update composer
   6625 	  ret = set_object_string(device, metadata->item_id, PTP_OPC_Composer, metadata->composer);
   6626 	  if (ret != 0) {
   6627 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6628 				    "could not set track composer name.");
   6629 	  }
   6630 	  break;
   6631 	case PTP_OPC_Genre:
   6632 	  // Update genre (but only if valid)
   6633 	  if (metadata->genre) {
   6634 	    ret = set_object_string(device, metadata->item_id, PTP_OPC_Genre, metadata->genre);
   6635 	    if (ret != 0) {
   6636 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   6637 				      "could not set genre.");
   6638 	    }
   6639 	  }
   6640 	  break;
   6641 	case PTP_OPC_Duration:
   6642 	  // Update duration
   6643 	  if (metadata->duration != 0) {
   6644 	    ret = set_object_u32(device, metadata->item_id, PTP_OPC_Duration, adjust_u32(metadata->duration, &opd));
   6645 	    if (ret != 0) {
   6646 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6647 				      "could not set track duration.");
   6648 	    }
   6649 	  }
   6650 	  break;
   6651 	case PTP_OPC_Track:
   6652 	  // Update track number.
   6653 	  if (metadata->tracknumber != 0) {
   6654 	    ret = set_object_u16(device, metadata->item_id, PTP_OPC_Track, adjust_u16(metadata->tracknumber, &opd));
   6655 	    if (ret != 0) {
   6656 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6657 				      "could not set track tracknumber.");
   6658 	    }
   6659 	  }
   6660 	  break;
   6661 	case PTP_OPC_OriginalReleaseDate:
   6662 	  // Update creation datetime
   6663 	  // The date can be zero, but some devices do not support setting zero
   6664 	  // dates (and it seems that a zero date should never be set anyway)
   6665 	  if (metadata->date) {
   6666 	    ret = set_object_string(device, metadata->item_id, PTP_OPC_OriginalReleaseDate, metadata->date);
   6667 	    if (ret != 0) {
   6668 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6669 				      "could not set track release date.");
   6670 	    }
   6671 	  }
   6672 	  break;
   6673 	  // These are, well not so important.
   6674 	case PTP_OPC_SampleRate:
   6675 	  // Update sample rate
   6676 	  if (metadata->samplerate != 0) {
   6677 	    ret = set_object_u32(device, metadata->item_id, PTP_OPC_SampleRate, adjust_u32(metadata->samplerate, &opd));
   6678 	    if (ret != 0) {
   6679 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6680 				      "could not set samplerate.");
   6681 	    }
   6682 	  }
   6683 	  break;
   6684 	case PTP_OPC_NumberOfChannels:
   6685 	  // Update number of channels
   6686 	  if (metadata->nochannels != 0) {
   6687 	    ret = set_object_u16(device, metadata->item_id, PTP_OPC_NumberOfChannels, adjust_u16(metadata->nochannels, &opd));
   6688 	  if (ret != 0) {
   6689 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6690 				    "could not set number of channels.");
   6691 	  }
   6692 	}
   6693 	  break;
   6694 	case PTP_OPC_AudioWAVECodec:
   6695 	  // Update WAVE codec
   6696 	  if (metadata->wavecodec != 0) {
   6697 	    ret = set_object_u32(device, metadata->item_id, PTP_OPC_AudioWAVECodec, adjust_u32(metadata->wavecodec, &opd));
   6698 	    if (ret != 0) {
   6699 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6700 				      "could not set WAVE codec.");
   6701 	    }
   6702 	  }
   6703 	  break;
   6704 	case PTP_OPC_AudioBitRate:
   6705 	  // Update bitrate
   6706 	  if (metadata->bitrate != 0) {
   6707 	    ret = set_object_u32(device, metadata->item_id, PTP_OPC_AudioBitRate, adjust_u32(metadata->bitrate, &opd));
   6708 	    if (ret != 0) {
   6709 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6710 				      "could not set bitrate.");
   6711 	  }
   6712 	  }
   6713 	  break;
   6714 	case PTP_OPC_BitRateType:
   6715 	  // Update bitrate type
   6716 	  if (metadata->bitratetype != 0) {
   6717 	    ret = set_object_u16(device, metadata->item_id, PTP_OPC_BitRateType, adjust_u16(metadata->bitratetype, &opd));
   6718 	    if (ret != 0) {
   6719 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6720 				      "could not set bitratetype.");
   6721 	    }
   6722 	  }
   6723 	  break;
   6724 	case PTP_OPC_Rating:
   6725 	  // Update user rating
   6726 	  // TODO: shall this be set for rating 0?
   6727 	  if (metadata->rating != 0) {
   6728 	    ret = set_object_u16(device, metadata->item_id, PTP_OPC_Rating, adjust_u16(metadata->rating, &opd));
   6729 	    if (ret != 0) {
   6730 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6731 				      "could not set user rating.");
   6732 	    }
   6733 	  }
   6734 	  break;
   6735 	case PTP_OPC_UseCount:
   6736 	  // Update use count, set even to zero if desired.
   6737 	  ret = set_object_u32(device, metadata->item_id, PTP_OPC_UseCount, adjust_u32(metadata->usecount, &opd));
   6738 	  if (ret != 0) {
   6739 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6740 				  "could not set use count.");
   6741 	  }
   6742 	  break;
   6743 	case PTP_OPC_DateModified:
   6744 	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
   6745 	    // Update modification time if supported
   6746 	    char *tmpstamp = get_iso8601_stamp();
   6747 	    ret = set_object_string(device, metadata->item_id, PTP_OPC_DateModified, tmpstamp);
   6748 	    if (ret != 0) {
   6749 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6750 				      "could not set modification date.");
   6751 	    }
   6752 	    free(tmpstamp);
   6753 	  }
   6754 	  break;
   6755 
   6756 	  // NOTE: File size is not updated, this should not change anyway.
   6757 	  // neither will we change the filename.
   6758 	default:
   6759 	  break;
   6760 	}
   6761       }
   6762       ptp_free_objectpropdesc(&opd);
   6763     }
   6764   } else {
   6765     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Update_Track_Metadata(): "
   6766                             "Your device doesn't seem to support any known way of setting metadata.");
   6767     free(properties);
   6768     return -1;
   6769   }
   6770 
   6771   // update cached object properties if metadata cache exists
   6772   update_metadata_cache(device, metadata->item_id);
   6773 
   6774   free(properties);
   6775 
   6776   return 0;
   6777 }
   6778 
   6779 /**
   6780  * This function deletes a single file, track, playlist, folder or
   6781  * any other object off the MTP device, identified by the object ID.
   6782  *
   6783  * If you delete a folder, there is no guarantee that the device will
   6784  * really delete all the files that were in that folder, rather it is
   6785  * expected that they will not be deleted, and will turn up in object
   6786  * listings with parent set to a non-existant object ID. The safe way
   6787  * to do this is to recursively delete all files (and folders) contained
   6788  * in the folder, then the folder itself.
   6789  *
   6790  * @param device a pointer to the device to delete the object from.
   6791  * @param object_id the object to delete.
   6792  * @return 0 on success, any other value means failure.
   6793  */
   6794 int LIBMTP_Delete_Object(LIBMTP_mtpdevice_t *device,
   6795 			 uint32_t object_id)
   6796 {
   6797   uint16_t ret;
   6798   PTPParams *params = (PTPParams *) device->params;
   6799 
   6800   ret = ptp_deleteobject(params, object_id, 0);
   6801   if (ret != PTP_RC_OK) {
   6802     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Delete_Object(): could not delete object.");
   6803     return -1;
   6804   }
   6805 
   6806   return 0;
   6807 }
   6808 
   6809 /**
   6810  * Internal function to update an object filename property.
   6811  */
   6812 static int set_object_filename(LIBMTP_mtpdevice_t *device,
   6813 			       uint32_t object_id, uint16_t ptp_type,
   6814 			       const char **newname_ptr)
   6815 {
   6816   PTPParams             *params = (PTPParams *) device->params;
   6817   PTP_USB               *ptp_usb = (PTP_USB*) device->usbinfo;
   6818   PTPObjectPropDesc     opd;
   6819   uint16_t              ret;
   6820   char                  *newname;
   6821 
   6822   // See if we can modify the filename on this kind of files.
   6823   ret = ptp_mtp_getobjectpropdesc(params, PTP_OPC_ObjectFileName, ptp_type, &opd);
   6824   if (ret != PTP_RC_OK) {
   6825     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
   6826 			    "could not get property description.");
   6827     return -1;
   6828   }
   6829 
   6830   if (!opd.GetSet) {
   6831     ptp_free_objectpropdesc(&opd);
   6832     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
   6833             " property is not settable.");
   6834     // TODO: we COULD actually upload/download the object here, if we feel
   6835     //       like wasting time for the user.
   6836     return -1;
   6837   }
   6838 
   6839   newname = strdup(*newname_ptr);
   6840 
   6841   if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
   6842     strip_7bit_from_utf8(newname);
   6843   }
   6844 
   6845   if (ptp_operation_issupported(params, PTP_OC_MTP_SetObjPropList) &&
   6846       !FLAG_BROKEN_SET_OBJECT_PROPLIST(ptp_usb)) {
   6847     MTPProperties *props = NULL;
   6848     MTPProperties *prop = NULL;
   6849     int nrofprops = 0;
   6850 
   6851     prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   6852     prop->ObjectHandle = object_id;
   6853     prop->property = PTP_OPC_ObjectFileName;
   6854     prop->datatype = PTP_DTC_STR;
   6855     prop->propval.str = newname;
   6856 
   6857     ret = ptp_mtp_setobjectproplist(params, props, nrofprops);
   6858 
   6859     ptp_destroy_object_prop_list(props, nrofprops);
   6860 
   6861     if (ret != PTP_RC_OK) {
   6862         add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
   6863               " could not set object property list.");
   6864         ptp_free_objectpropdesc(&opd);
   6865         return -1;
   6866     }
   6867   } else if (ptp_operation_issupported(params, PTP_OC_MTP_SetObjectPropValue)) {
   6868     ret = set_object_string(device, object_id, PTP_OPC_ObjectFileName, newname);
   6869     if (ret != 0) {
   6870       add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
   6871               " could not set object filename.");
   6872       ptp_free_objectpropdesc(&opd);
   6873       return -1;
   6874     }
   6875   } else {
   6876     free(newname);
   6877     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "set_object_filename(): "
   6878               " your device doesn't seem to support any known way of setting metadata.");
   6879     ptp_free_objectpropdesc(&opd);
   6880     return -1;
   6881   }
   6882 
   6883   ptp_free_objectpropdesc(&opd);
   6884 
   6885   // update cached object properties if metadata cache exists
   6886   update_metadata_cache(device, object_id);
   6887 
   6888   return 0;
   6889 }
   6890 
   6891 /**
   6892  * This function renames a single file.
   6893  * This simply means that the PTP_OPC_ObjectFileName property
   6894  * is updated, if this is supported by the device.
   6895  *
   6896  * @param device a pointer to the device that contains the file.
   6897  * @param file the file metadata of the file to rename.
   6898  *        On success, the filename member is updated. Be aware, that
   6899  *        this name can be different than newname depending of device restrictions.
   6900  * @param newname the new filename for this object.
   6901  * @return 0 on success, any other value means failure.
   6902  */
   6903 int LIBMTP_Set_File_Name(LIBMTP_mtpdevice_t *device,
   6904                    LIBMTP_file_t *file, const char *newname)
   6905 {
   6906   int         ret;
   6907 
   6908   ret = set_object_filename(device, file->item_id,
   6909 			    map_libmtp_type_to_ptp_type(file->filetype),
   6910 			    &newname);
   6911 
   6912   if (ret != 0) {
   6913     return ret;
   6914   }
   6915 
   6916   free(file->filename);
   6917   file->filename = strdup(newname);
   6918   return ret;
   6919 }
   6920 
   6921 /**
   6922  * This function renames a single folder.
   6923  * This simply means that the PTP_OPC_ObjectFileName property
   6924  * is updated, if this is supported by the device.
   6925  *
   6926  * @param device a pointer to the device that contains the file.
   6927  * @param folder the folder metadata of the folder to rename.
   6928  *        On success, the name member is updated. Be aware, that
   6929  *        this name can be different than newname depending of device restrictions.
   6930  * @param newname the new name for this object.
   6931  * @return 0 on success, any other value means failure.
   6932  */
   6933 int LIBMTP_Set_Folder_Name(LIBMTP_mtpdevice_t *device,
   6934                    LIBMTP_folder_t *folder, const char* newname)
   6935 {
   6936   int ret;
   6937 
   6938   ret = set_object_filename(device, folder->folder_id,
   6939 			    PTP_OFC_Association,
   6940 			    &newname);
   6941 
   6942   if (ret != 0) {
   6943     return ret;
   6944     }
   6945 
   6946   free(folder->name);
   6947   folder->name = strdup(newname);
   6948   return ret;
   6949 }
   6950 
   6951 /**
   6952  * This function renames a single track.
   6953  * This simply means that the PTP_OPC_ObjectFileName property
   6954  * is updated, if this is supported by the device.
   6955  *
   6956  * @param device a pointer to the device that contains the file.
   6957  * @param track the track metadata of the track to rename.
   6958  *        On success, the filename member is updated. Be aware, that
   6959  *        this name can be different than newname depending of device restrictions.
   6960  * @param newname the new filename for this object.
   6961  * @return 0 on success, any other value means failure.
   6962  */
   6963 int LIBMTP_Set_Track_Name(LIBMTP_mtpdevice_t *device,
   6964                    LIBMTP_track_t *track, const char* newname)
   6965 {
   6966   int         ret;
   6967 
   6968   ret = set_object_filename(device, track->item_id,
   6969 			    map_libmtp_type_to_ptp_type(track->filetype),
   6970 			    &newname);
   6971 
   6972   if (ret != 0) {
   6973     return ret;
   6974   }
   6975 
   6976   free(track->filename);
   6977   track->filename = strdup(newname);
   6978   return ret;
   6979 }
   6980 
   6981 /**
   6982  * This function renames a single playlist object file holder.
   6983  * This simply means that the <code>PTP_OPC_ObjectFileName</code>
   6984  * property is updated, if this is supported by the device.
   6985  * The playlist filename should nominally end with an extension
   6986  * like ".pla".
   6987  *
   6988  * NOTE: if you want to change the metadata the device display
   6989  * about a playlist you must <i>not</i> use this function,
   6990  * use <code>LIBMTP_Update_Playlist()</code> instead!
   6991  *
   6992  * @param device a pointer to the device that contains the file.
   6993  * @param playlist the playlist metadata of the playlist to rename.
   6994  *        On success, the name member is updated. Be aware, that
   6995  *        this name can be different than newname depending of device restrictions.
   6996  * @param newname the new name for this object.
   6997  * @return 0 on success, any other value means failure.
   6998  * @see LIBMTP_Update_Playlist()
   6999  */
   7000 int LIBMTP_Set_Playlist_Name(LIBMTP_mtpdevice_t *device,
   7001                    LIBMTP_playlist_t *playlist, const char* newname)
   7002 {
   7003   int ret;
   7004 
   7005   ret = set_object_filename(device, playlist->playlist_id,
   7006 			    PTP_OFC_MTP_AbstractAudioVideoPlaylist,
   7007 			    &newname);
   7008 
   7009   if (ret != 0) {
   7010     return ret;
   7011   }
   7012 
   7013   free(playlist->name);
   7014   playlist->name = strdup(newname);
   7015   return ret;
   7016 }
   7017 
   7018 /**
   7019  * This function renames a single album.
   7020  * This simply means that the <code>PTP_OPC_ObjectFileName</code>
   7021  * property is updated, if this is supported by the device.
   7022  * The album filename should nominally end with an extension
   7023  * like ".alb".
   7024  *
   7025  * NOTE: if you want to change the metadata the device display
   7026  * about a playlist you must <i>not</i> use this function,
   7027  * use <code>LIBMTP_Update_Album()</code> instead!
   7028  *
   7029  * @param device a pointer to the device that contains the file.
   7030  * @param album the album metadata of the album to rename.
   7031  *        On success, the name member is updated. Be aware, that
   7032  *        this name can be different than newname depending of device restrictions.
   7033  * @param newname the new name for this object.
   7034  * @return 0 on success, any other value means failure.
   7035  * @see LIBMTP_Update_Album()
   7036  */
   7037 int LIBMTP_Set_Album_Name(LIBMTP_mtpdevice_t *device,
   7038                    LIBMTP_album_t *album, const char* newname)
   7039 {
   7040   int ret;
   7041 
   7042   ret = set_object_filename(device, album->album_id,
   7043 			    PTP_OFC_MTP_AbstractAudioAlbum,
   7044 			    &newname);
   7045 
   7046   if (ret != 0) {
   7047     return ret;
   7048   }
   7049 
   7050   free(album->name);
   7051   album->name = strdup(newname);
   7052   return ret;
   7053 }
   7054 
   7055 /**
   7056  * THIS FUNCTION IS DEPRECATED. PLEASE UPDATE YOUR CODE IN ORDER
   7057  * NOT TO USE IT.
   7058  *
   7059  * @see LIBMTP_Set_File_Name()
   7060  * @see LIBMTP_Set_Track_Name()
   7061  * @see LIBMTP_Set_Folder_Name()
   7062  * @see LIBMTP_Set_Playlist_Name()
   7063  * @see LIBMTP_Set_Album_Name()
   7064  */
   7065 int LIBMTP_Set_Object_Filename(LIBMTP_mtpdevice_t *device,
   7066                    uint32_t object_id, char* newname)
   7067 {
   7068   int             ret;
   7069   LIBMTP_file_t   *file;
   7070 
   7071   file = LIBMTP_Get_Filemetadata(device, object_id);
   7072 
   7073   if (file == NULL) {
   7074     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Set_Object_Filename(): "
   7075 			    "could not get file metadata for target object.");
   7076     return -1;
   7077   }
   7078 
   7079   ret = set_object_filename(device, object_id, map_libmtp_type_to_ptp_type(file->filetype), (const char **) &newname);
   7080 
   7081   free(file);
   7082 
   7083   return ret;
   7084 }
   7085 
   7086 /**
   7087  * Helper function. This indicates if a track exists on the device
   7088  * @param device a pointer to the device to get the track from.
   7089  * @param id the track ID of the track to retrieve.
   7090  * @return TRUE (!=0) if the track exists, FALSE (0) if not
   7091  */
   7092 int LIBMTP_Track_Exists(LIBMTP_mtpdevice_t *device,
   7093            uint32_t const id)
   7094 {
   7095   PTPParams *params = (PTPParams *) device->params;
   7096   uint16_t ret;
   7097   PTPObject *ob;
   7098 
   7099   ret = ptp_object_want (params, id, 0, &ob);
   7100   if (ret == PTP_RC_OK)
   7101       return -1;
   7102   return 0;
   7103 }
   7104 
   7105 /**
   7106  * This creates a new folder structure and allocates memory
   7107  * for it. Notice that if you add strings to this structure they
   7108  * will be freed by the corresponding <code>LIBMTP_folder_track_t</code>
   7109  * operation later, so be careful of using strdup() when assigning
   7110  * strings, e.g.:
   7111  *
   7112  * @return a pointer to the newly allocated folder structure.
   7113  * @see LIBMTP_destroy_folder_t()
   7114  */
   7115 LIBMTP_folder_t *LIBMTP_new_folder_t(void)
   7116 {
   7117   LIBMTP_folder_t *new = (LIBMTP_folder_t *) malloc(sizeof(LIBMTP_folder_t));
   7118   if (new == NULL) {
   7119     return NULL;
   7120   }
   7121   new->folder_id = 0;
   7122   new->parent_id = 0;
   7123   new->storage_id = 0;
   7124   new->name = NULL;
   7125   new->sibling = NULL;
   7126   new->child = NULL;
   7127   return new;
   7128 }
   7129 
   7130 /**
   7131  * This recursively deletes the memory for a folder structure.
   7132  * This shall typically be called on a top-level folder list to
   7133  * detsroy the entire folder tree.
   7134  *
   7135  * @param folder folder structure to destroy
   7136  * @see LIBMTP_new_folder_t()
   7137  */
   7138 void LIBMTP_destroy_folder_t(LIBMTP_folder_t *folder)
   7139 {
   7140 
   7141   if(folder == NULL) {
   7142      return;
   7143   }
   7144 
   7145   //Destroy from the bottom up
   7146   if(folder->child != NULL) {
   7147      LIBMTP_destroy_folder_t(folder->child);
   7148   }
   7149 
   7150   if(folder->sibling != NULL) {
   7151     LIBMTP_destroy_folder_t(folder->sibling);
   7152   }
   7153 
   7154   if(folder->name != NULL) {
   7155     free(folder->name);
   7156   }
   7157 
   7158   free(folder);
   7159 }
   7160 
   7161 /**
   7162  * Helper function. Returns a folder structure for a
   7163  * specified id.
   7164  *
   7165  * @param folderlist list of folders to search
   7166  * @id id of folder to look for
   7167  * @return a folder or NULL if not found
   7168  */
   7169 LIBMTP_folder_t *LIBMTP_Find_Folder(LIBMTP_folder_t *folderlist, uint32_t id)
   7170 {
   7171   LIBMTP_folder_t *ret = NULL;
   7172 
   7173   if(folderlist == NULL) {
   7174     return NULL;
   7175   }
   7176 
   7177   if(folderlist->folder_id == id) {
   7178     return folderlist;
   7179   }
   7180 
   7181   if(folderlist->sibling) {
   7182     ret = LIBMTP_Find_Folder(folderlist->sibling, id);
   7183   }
   7184 
   7185   if(folderlist->child && ret == NULL) {
   7186     ret = LIBMTP_Find_Folder(folderlist->child, id);
   7187   }
   7188 
   7189   return ret;
   7190 }
   7191 
   7192 /**
   7193  * Function used to recursively get subfolders from params.
   7194  */
   7195 static LIBMTP_folder_t *get_subfolders_for_folder(LIBMTP_folder_t *list, uint32_t parent)
   7196 {
   7197   LIBMTP_folder_t *retfolders = NULL;
   7198   LIBMTP_folder_t *children, *iter, *curr;
   7199 
   7200   iter = list->sibling;
   7201   while(iter != list) {
   7202     if (iter->parent_id != parent) {
   7203       iter = iter->sibling;
   7204       continue;
   7205     }
   7206 
   7207     /* We know that iter is a child of 'parent', therefore we can safely
   7208      * hold on to 'iter' locally since no one else will steal it
   7209      * from the 'list' as we recurse. */
   7210     children = get_subfolders_for_folder(list, iter->folder_id);
   7211 
   7212     curr = iter;
   7213     iter = iter->sibling;
   7214 
   7215     // Remove curr from the list.
   7216     curr->child->sibling = curr->sibling;
   7217     curr->sibling->child = curr->child;
   7218 
   7219     // Attach the children to curr.
   7220     curr->child = children;
   7221 
   7222     // Put this folder into the list of siblings.
   7223     curr->sibling = retfolders;
   7224     retfolders = curr;
   7225   }
   7226 
   7227   return retfolders;
   7228 }
   7229 
   7230 /**
   7231  * This returns a list of all folders available
   7232  * on the current MTP device.
   7233  *
   7234  * @param device a pointer to the device to get the folder listing for.
   7235  * @param storage a storage ID to get the folder list from
   7236  * @return a list of folders
   7237  */
   7238  LIBMTP_folder_t *LIBMTP_Get_Folder_List_For_Storage(LIBMTP_mtpdevice_t *device,
   7239 						    uint32_t const storage)
   7240 {
   7241   PTPParams *params = (PTPParams *) device->params;
   7242   LIBMTP_folder_t head, *rv;
   7243   int i;
   7244 
   7245   // Get all the handles if we haven't already done that
   7246   if (params->nrofobjects == 0) {
   7247     flush_handles(device);
   7248   }
   7249 
   7250   /*
   7251    * This creates a temporary list of the folders, this is in a
   7252    * reverse order and uses the Folder pointers that are already
   7253    * in the Folder structure. From this we can then build up the
   7254    * folder hierarchy with only looking at this temporary list,
   7255    * and removing the folders from this temporary list as we go.
   7256    * This significantly reduces the number of operations that we
   7257    * have to do in building the folder hierarchy. Also since the
   7258    * temp list is in reverse order, when we prepend to the sibling
   7259    * list things are in the same order as they were originally
   7260    * in the handle list.
   7261    */
   7262   head.sibling = &head;
   7263   head.child = &head;
   7264   for (i = 0; i < params->nrofobjects; i++) {
   7265     LIBMTP_folder_t *folder;
   7266     PTPObject *ob;
   7267 
   7268     ob = &params->objects[i];
   7269     if (ob->oi.ObjectFormat != PTP_OFC_Association) {
   7270       continue;
   7271     }
   7272 
   7273     if (storage != PTP_GOH_ALL_STORAGE && storage != ob->oi.StorageID) {
   7274       continue;
   7275     }
   7276 
   7277     /*
   7278      * Do we know how to handle these? They are part
   7279      * of the MTP 1.0 specification paragraph 3.6.4.
   7280      * For AssociationDesc 0x00000001U ptp_mtp_getobjectreferences()
   7281      * should be called on these to get the contained objects, but
   7282      * we basically don't care. Hopefully parent_id is maintained for all
   7283      * children, because we rely on that instead.
   7284      */
   7285     if (ob->oi.AssociationDesc != 0x00000000U) {
   7286       LIBMTP_INFO("MTP extended association type 0x%08x encountered\n", ob->oi.AssociationDesc);
   7287     }
   7288 
   7289     // Create a folder struct...
   7290     folder = LIBMTP_new_folder_t();
   7291     if (folder == NULL) {
   7292       // malloc failure or so.
   7293       return NULL;
   7294     }
   7295     folder->folder_id = ob->oid;
   7296     folder->parent_id = ob->oi.ParentObject;
   7297     folder->storage_id = ob->oi.StorageID;
   7298     folder->name = (ob->oi.Filename) ? (char *)strdup(ob->oi.Filename) : NULL;
   7299 
   7300     // pretend sibling says next, and child says prev.
   7301     folder->sibling = head.sibling;
   7302     folder->child = &head;
   7303     head.sibling->child = folder;
   7304     head.sibling = folder;
   7305   }
   7306 
   7307   // We begin at the given root folder and get them all recursively
   7308   rv = get_subfolders_for_folder(&head, 0x00000000U);
   7309 
   7310   // Some buggy devices may have some files in the "root folder"
   7311   // 0xffffffff so if 0x00000000 didn't return any folders,
   7312   // look for children of the root 0xffffffffU
   7313   if (rv == NULL) {
   7314     rv = get_subfolders_for_folder(&head, 0xffffffffU);
   7315     if (rv != NULL)
   7316       LIBMTP_ERROR("Device have files in \"root folder\" 0xffffffffU - "
   7317 		   "this is a firmware bug (but continuing)\n");
   7318   }
   7319 
   7320   // The temp list should be empty. Clean up any orphans just in case.
   7321   while(head.sibling != &head) {
   7322     LIBMTP_folder_t *curr = head.sibling;
   7323 
   7324     LIBMTP_INFO("Orphan folder with ID: 0x%08x name: \"%s\" encountered.\n",
   7325 	   curr->folder_id,
   7326 	   curr->name);
   7327     curr->sibling->child = curr->child;
   7328     curr->child->sibling = curr->sibling;
   7329     curr->child = NULL;
   7330     curr->sibling = NULL;
   7331     LIBMTP_destroy_folder_t(curr);
   7332   }
   7333 
   7334   return rv;
   7335 }
   7336 
   7337 /**
   7338  * This returns a list of all folders available
   7339  * on the current MTP device.
   7340  *
   7341  * @param device a pointer to the device to get the folder listing for.
   7342  * @return a list of folders
   7343  */
   7344 LIBMTP_folder_t *LIBMTP_Get_Folder_List(LIBMTP_mtpdevice_t *device)
   7345 {
   7346   return LIBMTP_Get_Folder_List_For_Storage(device, PTP_GOH_ALL_STORAGE);
   7347 }
   7348 
   7349 /**
   7350  * This create a folder on the current MTP device. The PTP name
   7351  * for a folder is "association". The PTP/MTP devices does not
   7352  * have an internal "folder" concept really, it contains a flat
   7353  * list of all files and some file are "associations" that other
   7354  * files and folders may refer to as its "parent".
   7355  *
   7356  * @param device a pointer to the device to create the folder on.
   7357  * @param name the name of the new folder. Note this can be modified
   7358  *        if the device does not support all the characters in the
   7359  *        name.
   7360  * @param parent_id id of parent folder to add the new folder to,
   7361  *        or 0xFFFFFFFF to put it in the root directory.
   7362  * @param storage_id id of the storage to add this new folder to.
   7363  *        notice that you cannot mismatch storage id and parent id:
   7364  *        they must both be on the same storage! Pass in 0 if you
   7365  *        want to create this folder on the default storage.
   7366  * @return id to new folder or 0 if an error occured
   7367  */
   7368 uint32_t LIBMTP_Create_Folder(LIBMTP_mtpdevice_t *device, char *name,
   7369 			      uint32_t parent_id, uint32_t storage_id)
   7370 {
   7371   PTPParams *params = (PTPParams *) device->params;
   7372   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   7373   uint32_t parenthandle = 0;
   7374   uint32_t store;
   7375   PTPObjectInfo new_folder;
   7376   uint16_t ret;
   7377   uint32_t new_id = 0;
   7378 
   7379   if (storage_id == 0) {
   7380     // I'm just guessing that a folder may require 512 bytes
   7381     store = get_suggested_storage_id(device, 512, parent_id);
   7382   } else {
   7383     store = storage_id;
   7384   }
   7385   parenthandle = parent_id;
   7386 
   7387   memset(&new_folder, 0, sizeof(new_folder));
   7388   new_folder.Filename = name;
   7389   if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
   7390     strip_7bit_from_utf8(new_folder.Filename);
   7391   }
   7392   new_folder.ObjectCompressedSize = 0;
   7393   new_folder.ObjectFormat = PTP_OFC_Association;
   7394   new_folder.ProtectionStatus = PTP_PS_NoProtection;
   7395   new_folder.AssociationType = PTP_AT_GenericFolder;
   7396   new_folder.ParentObject = parent_id;
   7397   new_folder.StorageID = store;
   7398 
   7399   // Create the object
   7400   if (!(params->device_flags & DEVICE_FLAG_BROKEN_SEND_OBJECT_PROPLIST) &&
   7401 	ptp_operation_issupported(params,PTP_OC_MTP_SendObjectPropList)) {
   7402 	MTPProperties *props = (MTPProperties*)calloc(2,sizeof(MTPProperties));
   7403 
   7404 	props[0].property = PTP_OPC_ObjectFileName;
   7405 	props[0].datatype = PTP_DTC_STR;
   7406 	props[0].propval.str = name;
   7407 
   7408 	props[1].property = PTP_OPC_Name;
   7409 	props[1].datatype = PTP_DTC_STR;
   7410 	props[1].propval.str = name;
   7411 
   7412 	ret = ptp_mtp_sendobjectproplist(params, &store, &parenthandle, &new_id, PTP_OFC_Association,
   7413 			0, props, 1);
   7414 	free(props);
   7415   } else {
   7416 	ret = ptp_sendobjectinfo(params, &store, &parenthandle, &new_id, &new_folder);
   7417   }
   7418 
   7419   if (ret != PTP_RC_OK) {
   7420     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Create_Folder: Could not send object info.");
   7421     if (ret == PTP_RC_AccessDenied) {
   7422       add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
   7423     }
   7424     return 0;
   7425   }
   7426   // NOTE: don't destroy the new_folder objectinfo, because it is statically referencing
   7427   // several strings.
   7428 
   7429   add_object_to_cache(device, new_id);
   7430 
   7431   return new_id;
   7432 }
   7433 
   7434 /**
   7435  * This creates a new playlist metadata structure and allocates memory
   7436  * for it. Notice that if you add strings to this structure they
   7437  * will be freed by the corresponding <code>LIBMTP_destroy_playlist_t</code>
   7438  * operation later, so be careful of using strdup() when assigning
   7439  * strings, e.g.:
   7440  *
   7441  * <pre>
   7442  * LIBMTP_playlist_t *pl = LIBMTP_new_playlist_t();
   7443  * pl->name = strdup(str);
   7444  * ....
   7445  * LIBMTP_destroy_playlist_t(pl);
   7446  * </pre>
   7447  *
   7448  * @return a pointer to the newly allocated metadata structure.
   7449  * @see LIBMTP_destroy_playlist_t()
   7450  */
   7451 LIBMTP_playlist_t *LIBMTP_new_playlist_t(void)
   7452 {
   7453   LIBMTP_playlist_t *new = (LIBMTP_playlist_t *) malloc(sizeof(LIBMTP_playlist_t));
   7454   if (new == NULL) {
   7455     return NULL;
   7456   }
   7457   new->playlist_id = 0;
   7458   new->parent_id = 0;
   7459   new->storage_id = 0;
   7460   new->name = NULL;
   7461   new->tracks = NULL;
   7462   new->no_tracks = 0;
   7463   new->next = NULL;
   7464   return new;
   7465 }
   7466 
   7467 /**
   7468  * This destroys a playlist metadata structure and deallocates the memory
   7469  * used by it, including any strings. Never use a track metadata
   7470  * structure again after calling this function on it.
   7471  * @param playlist the playlist metadata to destroy.
   7472  * @see LIBMTP_new_playlist_t()
   7473  */
   7474 void LIBMTP_destroy_playlist_t(LIBMTP_playlist_t *playlist)
   7475 {
   7476   if (playlist == NULL) {
   7477     return;
   7478   }
   7479   if (playlist->name != NULL)
   7480     free(playlist->name);
   7481   if (playlist->tracks != NULL)
   7482     free(playlist->tracks);
   7483   free(playlist);
   7484   return;
   7485 }
   7486 
   7487 /**
   7488  * This function returns a list of the playlists available on the
   7489  * device. Typical usage:
   7490  *
   7491  * <pre>
   7492  * </pre>
   7493  *
   7494  * @param device a pointer to the device to get the playlist listing from.
   7495  * @return a playlist list on success, else NULL. If there are no playlists
   7496  *         on the device, NULL will be returned as well.
   7497  * @see LIBMTP_Get_Playlist()
   7498  */
   7499 LIBMTP_playlist_t *LIBMTP_Get_Playlist_List(LIBMTP_mtpdevice_t *device)
   7500 {
   7501   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   7502   const int REQ_SPL = FLAG_PLAYLIST_SPL(ptp_usb);
   7503   PTPParams *params = (PTPParams *) device->params;
   7504   LIBMTP_playlist_t *retlists = NULL;
   7505   LIBMTP_playlist_t *curlist = NULL;
   7506   uint32_t i;
   7507 
   7508   // Get all the handles if we haven't already done that
   7509   if (params->nrofobjects == 0) {
   7510     flush_handles(device);
   7511   }
   7512 
   7513   for (i = 0; i < params->nrofobjects; i++) {
   7514     LIBMTP_playlist_t *pl;
   7515     PTPObject *ob;
   7516     uint16_t ret;
   7517 
   7518     ob = &params->objects[i];
   7519 
   7520     // Ignore stuff that isn't playlists
   7521 
   7522     // For Samsung players we must look for the .spl extension explicitly since
   7523     // playlists are not stored as playlist objects.
   7524     if ( REQ_SPL && is_spl_playlist(&ob->oi) ) {
   7525       // Allocate a new playlist type
   7526       pl = LIBMTP_new_playlist_t();
   7527       spl_to_playlist_t(device, &ob->oi, ob->oid, pl);
   7528     }
   7529     else if ( ob->oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioVideoPlaylist ) {
   7530       continue;
   7531     }
   7532     else {
   7533       // Allocate a new playlist type
   7534       pl = LIBMTP_new_playlist_t();
   7535 
   7536       // Try to look up proper name, else use the oi->Filename field.
   7537       pl->name = get_string_from_object(device, ob->oid, PTP_OPC_Name);
   7538       if (pl->name == NULL) {
   7539 	pl->name = strdup(ob->oi.Filename);
   7540       }
   7541       pl->playlist_id = ob->oid;
   7542       pl->parent_id = ob->oi.ParentObject;
   7543       pl->storage_id = ob->oi.StorageID;
   7544 
   7545       // Then get the track listing for this playlist
   7546       ret = ptp_mtp_getobjectreferences(params, pl->playlist_id, &pl->tracks, &pl->no_tracks);
   7547       if (ret != PTP_RC_OK) {
   7548         add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Playlist_List(): "
   7549 				    "could not get object references.");
   7550         pl->tracks = NULL;
   7551         pl->no_tracks = 0;
   7552       }
   7553     }
   7554 
   7555     // Add playlist to a list that will be returned afterwards.
   7556     if (retlists == NULL) {
   7557       retlists = pl;
   7558       curlist = pl;
   7559     } else {
   7560       curlist->next = pl;
   7561       curlist = pl;
   7562     }
   7563 
   7564     // Call callback here if we decide to add that possibility...
   7565   }
   7566   return retlists;
   7567 }
   7568 
   7569 
   7570 /**
   7571  * This function retrieves an individual playlist from the device.
   7572  * @param device a pointer to the device to get the playlist from.
   7573  * @param plid the unique ID of the playlist to retrieve.
   7574  * @return a valid playlist metadata post or NULL on failure.
   7575  * @see LIBMTP_Get_Playlist_List()
   7576  */
   7577 LIBMTP_playlist_t *LIBMTP_Get_Playlist(LIBMTP_mtpdevice_t *device, uint32_t const plid)
   7578 {
   7579   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   7580   const int REQ_SPL = FLAG_PLAYLIST_SPL(ptp_usb);
   7581   PTPParams *params = (PTPParams *) device->params;
   7582   PTPObject *ob;
   7583   LIBMTP_playlist_t *pl;
   7584   uint16_t ret;
   7585 
   7586   // Get all the handles if we haven't already done that
   7587   if (params->nrofobjects == 0) {
   7588     flush_handles(device);
   7589   }
   7590 
   7591   ret = ptp_object_want (params, plid, PTPOBJECT_OBJECTINFO_LOADED, &ob);
   7592   if (ret != PTP_RC_OK)
   7593     return NULL;
   7594 
   7595   // For Samsung players we must look for the .spl extension explicitly since
   7596   // playlists are not stored as playlist objects.
   7597   if ( REQ_SPL && is_spl_playlist(&ob->oi) ) {
   7598     // Allocate a new playlist type
   7599     pl = LIBMTP_new_playlist_t();
   7600     spl_to_playlist_t(device, &ob->oi, ob->oid, pl);
   7601     return pl;
   7602   }
   7603 
   7604   // Ignore stuff that isn't playlists
   7605   else if ( ob->oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioVideoPlaylist ) {
   7606     return NULL;
   7607   }
   7608 
   7609   // Allocate a new playlist type
   7610   pl = LIBMTP_new_playlist_t();
   7611 
   7612   pl->name = get_string_from_object(device, ob->oid, PTP_OPC_Name);
   7613   if (pl->name == NULL) {
   7614     pl->name = strdup(ob->oi.Filename);
   7615   }
   7616   pl->playlist_id = ob->oid;
   7617   pl->parent_id = ob->oi.ParentObject;
   7618   pl->storage_id = ob->oi.StorageID;
   7619 
   7620   // Then get the track listing for this playlist
   7621   ret = ptp_mtp_getobjectreferences(params, pl->playlist_id, &pl->tracks, &pl->no_tracks);
   7622   if (ret != PTP_RC_OK) {
   7623     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Playlist(): Could not get object references.");
   7624     pl->tracks = NULL;
   7625     pl->no_tracks = 0;
   7626   }
   7627 
   7628   return pl;
   7629 }
   7630 
   7631 /**
   7632  * This function creates a new abstract list such as a playlist
   7633  * or an album.
   7634  *
   7635  * @param device a pointer to the device to create the new abstract list
   7636  *        on.
   7637  * @param name the name of the new abstract list.
   7638  * @param artist the artist of the new abstract list or NULL.
   7639  * @param genre the genre of the new abstract list or NULL.
   7640  * @param parenthandle the handle of the parent or 0 for no parent
   7641  *        i.e. the root folder.
   7642  * @param objectformat the abstract list type to create.
   7643  * @param suffix the ".foo" (4 characters) suffix to use for the virtual
   7644  *        "file" created by this operation.
   7645  * @param newid a pointer to a variable that will hold the new object
   7646  *        ID if this call is successful.
   7647  * @param tracks an array of tracks to associate with this list.
   7648  * @param no_tracks the number of tracks in the list.
   7649  * @return 0 on success, any other value means failure.
   7650  */
   7651 static int create_new_abstract_list(LIBMTP_mtpdevice_t *device,
   7652 				    char const * const name,
   7653 				    char const * const artist,
   7654 				    char const * const composer,
   7655 				    char const * const genre,
   7656 				    uint32_t const parenthandle,
   7657 				    uint32_t const storageid,
   7658 				    uint16_t const objectformat,
   7659 				    char const * const suffix,
   7660 				    uint32_t * const newid,
   7661 				    uint32_t const * const tracks,
   7662 				    uint32_t const no_tracks)
   7663 
   7664 {
   7665   int i;
   7666   int supported = 0;
   7667   uint16_t ret;
   7668   uint16_t *properties = NULL;
   7669   uint32_t propcnt = 0;
   7670   uint32_t store;
   7671   uint32_t localph = parenthandle;
   7672   uint8_t nonconsumable = 0x00U; /* By default it is consumable */
   7673   PTPParams *params = (PTPParams *) device->params;
   7674   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   7675   char fname[256];
   7676   //uint8_t data[2];
   7677 
   7678   // NULL check
   7679   if (!name) {
   7680     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): list name was NULL, using default name \"Unknown\"");
   7681     return -1;
   7682   }
   7683 
   7684   if (storageid == 0) {
   7685     // I'm just guessing that an abstract list may require 512 bytes
   7686     store = get_suggested_storage_id(device, 512, localph);
   7687   } else {
   7688     store = storageid;
   7689   }
   7690 
   7691   // Check if we can create an object of this type
   7692   for ( i=0; i < params->deviceinfo.ImageFormats_len; i++ ) {
   7693     if (params->deviceinfo.ImageFormats[i] == objectformat) {
   7694       supported = 1;
   7695       break;
   7696     }
   7697   }
   7698   if (!supported) {
   7699     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): player does not support this abstract type");
   7700     LIBMTP_ERROR("Unsupported abstract list type: %04x\n", objectformat);
   7701     return -1;
   7702   }
   7703 
   7704   // add the new suffix if it isn't there
   7705   fname[0] = '\0';
   7706   if (strlen(name) > strlen(suffix)) {
   7707     char const * const suff = &name[strlen(name)-strlen(suffix)];
   7708     if (!strcmp(suff, suffix)) {
   7709       // Home free.
   7710       strncpy(fname, name, sizeof(fname));
   7711     }
   7712   }
   7713   // If it didn't end with "<suffix>" then add that here.
   7714   if (fname[0] == '\0') {
   7715     strncpy(fname, name, sizeof(fname)-strlen(suffix)-1);
   7716     strcat(fname, suffix);
   7717     fname[sizeof(fname)-1] = '\0';
   7718   }
   7719 
   7720   if (ptp_operation_issupported(params, PTP_OC_MTP_SendObjectPropList) &&
   7721       !FLAG_BROKEN_SEND_OBJECT_PROPLIST(ptp_usb)) {
   7722     MTPProperties *props = NULL;
   7723     MTPProperties *prop = NULL;
   7724     int nrofprops = 0;
   7725 
   7726     *newid = 0x00000000U;
   7727 
   7728     ret = ptp_mtp_getobjectpropssupported(params, objectformat, &propcnt, &properties);
   7729 
   7730     for (i=0;i<propcnt;i++) {
   7731       PTPObjectPropDesc opd;
   7732 
   7733       ret = ptp_mtp_getobjectpropdesc(params, properties[i], objectformat, &opd);
   7734       if (ret != PTP_RC_OK) {
   7735 	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): "
   7736 				"could not get property description.");
   7737       } else if (opd.GetSet) {
   7738 	switch (properties[i]) {
   7739 	case PTP_OPC_ObjectFileName:
   7740 	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7741 	  prop->ObjectHandle = *newid;
   7742 	  prop->property = PTP_OPC_ObjectFileName;
   7743 	  prop->datatype = PTP_DTC_STR;
   7744 	  prop->propval.str = strdup(fname);
   7745 	  if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
   7746 	    strip_7bit_from_utf8(prop->propval.str);
   7747 	  }
   7748 	  break;
   7749 	case PTP_OPC_ProtectionStatus:
   7750 	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7751 	  prop->ObjectHandle = *newid;
   7752 	  prop->property = PTP_OPC_ProtectionStatus;
   7753 	  prop->datatype = PTP_DTC_UINT16;
   7754 	  prop->propval.u16 = 0x0000U; /* Not protected */
   7755 	  break;
   7756 	case PTP_OPC_NonConsumable:
   7757 	  prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7758 	  prop->ObjectHandle = *newid;
   7759 	  prop->property = PTP_OPC_NonConsumable;
   7760 	  prop->datatype = PTP_DTC_UINT8;
   7761 	  prop->propval.u8 = nonconsumable;
   7762 	  break;
   7763 	case PTP_OPC_Name:
   7764 	  if (name != NULL) {
   7765 	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7766 	    prop->ObjectHandle = *newid;
   7767 	    prop->property = PTP_OPC_Name;
   7768 	    prop->datatype = PTP_DTC_STR;
   7769 	    prop->propval.str = strdup(name);
   7770 	  }
   7771 	  break;
   7772 	case PTP_OPC_AlbumArtist:
   7773 	  if (artist != NULL) {
   7774 	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7775 	    prop->ObjectHandle = *newid;
   7776 	    prop->property = PTP_OPC_AlbumArtist;
   7777 	    prop->datatype = PTP_DTC_STR;
   7778 	    prop->propval.str = strdup(artist);
   7779 	  }
   7780 	  break;
   7781 	case PTP_OPC_Artist:
   7782 	  if (artist != NULL) {
   7783 	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7784 	    prop->ObjectHandle = *newid;
   7785 	    prop->property = PTP_OPC_Artist;
   7786 	    prop->datatype = PTP_DTC_STR;
   7787 	    prop->propval.str = strdup(artist);
   7788 	  }
   7789 	  break;
   7790 	case PTP_OPC_Composer:
   7791 	  if (composer != NULL) {
   7792 	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7793 	    prop->ObjectHandle = *newid;
   7794 	    prop->property = PTP_OPC_Composer;
   7795 	    prop->datatype = PTP_DTC_STR;
   7796 	    prop->propval.str = strdup(composer);
   7797 	  }
   7798 	  break;
   7799 	case PTP_OPC_Genre:
   7800 	  if (genre != NULL) {
   7801 	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7802 	    prop->ObjectHandle = *newid;
   7803 	    prop->property = PTP_OPC_Genre;
   7804 	    prop->datatype = PTP_DTC_STR;
   7805 	    prop->propval.str = strdup(genre);
   7806 	  }
   7807 	  break;
   7808  	case PTP_OPC_DateModified:
   7809 	  // Tag with current time if that is supported
   7810 	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
   7811 	    prop = ptp_get_new_object_prop_entry(&props,&nrofprops);
   7812 	    prop->ObjectHandle = *newid;
   7813 	    prop->property = PTP_OPC_DateModified;
   7814 	    prop->datatype = PTP_DTC_STR;
   7815 	    prop->propval.str = get_iso8601_stamp();
   7816 	  }
   7817 	  break;
   7818 	}
   7819       }
   7820       ptp_free_objectpropdesc(&opd);
   7821     }
   7822     free(properties);
   7823 
   7824     ret = ptp_mtp_sendobjectproplist(params, &store, &localph, newid,
   7825 				     objectformat, 0, props, nrofprops);
   7826 
   7827     /* Free property list */
   7828     ptp_destroy_object_prop_list(props, nrofprops);
   7829 
   7830     if (ret != PTP_RC_OK) {
   7831       add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): Could not send object property list.");
   7832       if (ret == PTP_RC_AccessDenied) {
   7833 	add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
   7834       }
   7835       return -1;
   7836     }
   7837 
   7838     // now send the blank object
   7839     ret = ptp_sendobject(params, NULL, 0);
   7840     if (ret != PTP_RC_OK) {
   7841       add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): Could not send blank object data.");
   7842       return -1;
   7843     }
   7844 
   7845   } else if (ptp_operation_issupported(params,PTP_OC_SendObjectInfo)) {
   7846     PTPObjectInfo new_object;
   7847 
   7848     new_object.Filename = fname;
   7849     if (FLAG_ONLY_7BIT_FILENAMES(ptp_usb)) {
   7850       strip_7bit_from_utf8(new_object.Filename);
   7851     }
   7852     // At one point this had to be one
   7853     new_object.ObjectCompressedSize = 0;
   7854     new_object.ObjectFormat = objectformat;
   7855 
   7856     // Create the object
   7857     ret = ptp_sendobjectinfo(params, &store, &localph, newid, &new_object);
   7858     if (ret != PTP_RC_OK) {
   7859       add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): Could not send object info (the playlist itself).");
   7860       if (ret == PTP_RC_AccessDenied) {
   7861 	add_ptp_error_to_errorstack(device, ret, "ACCESS DENIED.");
   7862       }
   7863       return -1;
   7864     }
   7865     // NOTE: don't destroy new_object objectinfo afterwards - the strings it contains are
   7866     // not copies.
   7867 
   7868 #if 0
   7869     /*
   7870      * At one time we had to send this one blank data byte.
   7871      * If we didn't, the handle will not be created and thus there is
   7872      * no playlist. Possibly this was masking some bug, so removing it
   7873      * now.
   7874      */
   7875     data[0] = '\0';
   7876     data[1] = '\0';
   7877     ret = ptp_sendobject(params, data, 1);
   7878     if (ret != PTP_RC_OK) {
   7879       add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): Could not send blank object data.");
   7880       return -1;
   7881     }
   7882 #endif
   7883 
   7884     // set the properties one by one
   7885     ret = ptp_mtp_getobjectpropssupported(params, objectformat, &propcnt, &properties);
   7886 
   7887     for (i=0;i<propcnt;i++) {
   7888       PTPObjectPropDesc opd;
   7889 
   7890       ret = ptp_mtp_getobjectpropdesc(params, properties[i], objectformat, &opd);
   7891       if (ret != PTP_RC_OK) {
   7892 	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): "
   7893 				"could not get property description.");
   7894       } else if (opd.GetSet) {
   7895 	switch (properties[i]) {
   7896 	case PTP_OPC_Name:
   7897 	  if (name != NULL) {
   7898 	    ret = set_object_string(device, *newid, PTP_OPC_Name, name);
   7899 	    if (ret != 0) {
   7900 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity name.");
   7901 	      return -1;
   7902 	    }
   7903 	  }
   7904 	  break;
   7905 	case PTP_OPC_AlbumArtist:
   7906 	  if (artist != NULL) {
   7907 	    ret = set_object_string(device, *newid, PTP_OPC_AlbumArtist, artist);
   7908 	    if (ret != 0) {
   7909 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity album artist.");
   7910 	      return -1;
   7911 	    }
   7912 	  }
   7913 	  break;
   7914 	case PTP_OPC_Artist:
   7915 	  if (artist != NULL) {
   7916 	    ret = set_object_string(device, *newid, PTP_OPC_Artist, artist);
   7917 	    if (ret != 0) {
   7918 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity artist.");
   7919 	      return -1;
   7920 	    }
   7921 	  }
   7922 	  break;
   7923 	case PTP_OPC_Composer:
   7924 	  if (composer != NULL) {
   7925 	    ret = set_object_string(device, *newid, PTP_OPC_Composer, composer);
   7926 	    if (ret != 0) {
   7927 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity composer.");
   7928 	      return -1;
   7929 	    }
   7930 	  }
   7931 	  break;
   7932 	case PTP_OPC_Genre:
   7933 	  if (genre != NULL) {
   7934 	    ret = set_object_string(device, *newid, PTP_OPC_Genre, genre);
   7935 	    if (ret != 0) {
   7936 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set entity genre.");
   7937 	      return -1;
   7938 	    }
   7939 	  }
   7940 	  break;
   7941  	case PTP_OPC_DateModified:
   7942 	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
   7943 	    ret = set_object_string(device, *newid, PTP_OPC_DateModified, get_iso8601_stamp());
   7944 	    if (ret != 0) {
   7945 	      add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "create_new_abstract_list(): could not set date modified.");
   7946 	      return -1;
   7947 	    }
   7948 	  }
   7949 	  break;
   7950 	}
   7951       }
   7952       ptp_free_objectpropdesc(&opd);
   7953     }
   7954     free(properties);
   7955   }
   7956 
   7957   if (no_tracks > 0) {
   7958     // Add tracks to the list as object references.
   7959     ret = ptp_mtp_setobjectreferences (params, *newid, (uint32_t *) tracks, no_tracks);
   7960     if (ret != PTP_RC_OK) {
   7961       add_ptp_error_to_errorstack(device, ret, "create_new_abstract_list(): could not add tracks as object references.");
   7962       return -1;
   7963     }
   7964   }
   7965 
   7966   add_object_to_cache(device, *newid);
   7967 
   7968   return 0;
   7969 }
   7970 
   7971 /**
   7972  * This updates the metadata and track listing
   7973  * for an abstract list.
   7974  * @param device a pointer to the device that the abstract list
   7975  *        resides on.
   7976  * @param name the name of the abstract list.
   7977  * @param artist the artist of the abstract list or NULL.
   7978  * @param genre the genre of the abstract list or NULL.
   7979  * @param objecthandle the object to be updated.
   7980  * @param objectformat the abstract list type to update.
   7981  * @param tracks an array of tracks to associate with this list.
   7982  * @param no_tracks the number of tracks in the list.
   7983  * @return 0 on success, any other value means failure.
   7984  */
   7985 static int update_abstract_list(LIBMTP_mtpdevice_t *device,
   7986 				char const * const name,
   7987 				char const * const artist,
   7988 				char const * const composer,
   7989 				char const * const genre,
   7990 				uint32_t const objecthandle,
   7991 				uint16_t const objectformat,
   7992 				uint32_t const * const tracks,
   7993 				uint32_t const no_tracks)
   7994 {
   7995   uint16_t ret;
   7996   PTPParams *params = (PTPParams *) device->params;
   7997   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   7998   uint16_t *properties = NULL;
   7999   uint32_t propcnt = 0;
   8000   int i;
   8001 
   8002   // First see which properties can be set
   8003   // i.e only try to update this metadata for object tags that exist on the current player.
   8004   ret = ptp_mtp_getobjectpropssupported(params, objectformat, &propcnt, &properties);
   8005   if (ret != PTP_RC_OK) {
   8006     // Just bail out for now, nothing is ever set.
   8007     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8008 			    "could not retrieve supported object properties.");
   8009     return -1;
   8010   }
   8011   if (ptp_operation_issupported(params,PTP_OC_MTP_SetObjPropList) &&
   8012       !FLAG_BROKEN_SET_OBJECT_PROPLIST(ptp_usb)) {
   8013     MTPProperties *props = NULL;
   8014     MTPProperties *prop = NULL;
   8015     int nrofprops = 0;
   8016 
   8017     for (i=0;i<propcnt;i++) {
   8018       PTPObjectPropDesc opd;
   8019 
   8020       ret = ptp_mtp_getobjectpropdesc(params, properties[i], objectformat, &opd);
   8021       if (ret != PTP_RC_OK) {
   8022 	add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8023 				"could not get property description.");
   8024       } else if (opd.GetSet) {
   8025 	switch (properties[i]) {
   8026 	case PTP_OPC_Name:
   8027 	  prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   8028 	  prop->ObjectHandle = objecthandle;
   8029 	  prop->property = PTP_OPC_Name;
   8030 	  prop->datatype = PTP_DTC_STR;
   8031 	  if (name != NULL)
   8032 	    prop->propval.str = strdup(name);
   8033 	  break;
   8034 	case PTP_OPC_AlbumArtist:
   8035 	  if (artist != NULL) {
   8036 	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   8037 	    prop->ObjectHandle = objecthandle;
   8038 	    prop->property = PTP_OPC_AlbumArtist;
   8039 	    prop->datatype = PTP_DTC_STR;
   8040 	    prop->propval.str = strdup(artist);
   8041 	  }
   8042 	  break;
   8043 	case PTP_OPC_Artist:
   8044 	  if (artist != NULL) {
   8045 	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   8046 	    prop->ObjectHandle = objecthandle;
   8047 	    prop->property = PTP_OPC_Artist;
   8048 	    prop->datatype = PTP_DTC_STR;
   8049 	    prop->propval.str = strdup(artist);
   8050 	  }
   8051 	  break;
   8052 	case PTP_OPC_Composer:
   8053 	  if (composer != NULL) {
   8054 	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   8055 	    prop->ObjectHandle = objecthandle;
   8056 	    prop->property = PTP_OPC_Composer;
   8057 	    prop->datatype = PTP_DTC_STR;
   8058 	    prop->propval.str = strdup(composer);
   8059 	  }
   8060 	  break;
   8061 	case PTP_OPC_Genre:
   8062 	  if (genre != NULL) {
   8063 	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   8064 	    prop->ObjectHandle = objecthandle;
   8065 	    prop->property = PTP_OPC_Genre;
   8066 	    prop->datatype = PTP_DTC_STR;
   8067 	    prop->propval.str = strdup(genre);
   8068 	  }
   8069 	  break;
   8070  	case PTP_OPC_DateModified:
   8071 	  if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
   8072 	    // Tag with current time if that is supported
   8073 	    prop = ptp_get_new_object_prop_entry(&props, &nrofprops);
   8074 	    prop->ObjectHandle = objecthandle;
   8075 	    prop->property = PTP_OPC_DateModified;
   8076 	    prop->datatype = PTP_DTC_STR;
   8077 	    prop->propval.str = get_iso8601_stamp();
   8078 	  }
   8079 	  break;
   8080 	default:
   8081 	  break;
   8082 	}
   8083       }
   8084       ptp_free_objectpropdesc(&opd);
   8085     }
   8086 
   8087     // proplist could be NULL if we can't write any properties
   8088     if (props != NULL) {
   8089       ret = ptp_mtp_setobjectproplist(params, props, nrofprops);
   8090 
   8091       ptp_destroy_object_prop_list(props, nrofprops);
   8092 
   8093       if (ret != PTP_RC_OK) {
   8094         // TODO: return error of which property we couldn't set
   8095         add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8096                                 "could not set object property list.");
   8097         free(properties);
   8098         return -1;
   8099       }
   8100     }
   8101 
   8102   } else if (ptp_operation_issupported(params,PTP_OC_MTP_SetObjectPropValue)) {
   8103     for (i=0;i<propcnt;i++) {
   8104       switch (properties[i]) {
   8105       case PTP_OPC_Name:
   8106 	// Update title
   8107 	ret = set_object_string(device, objecthandle, PTP_OPC_Name, name);
   8108 	if (ret != 0) {
   8109 	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8110 				  "could not set title.");
   8111 	}
   8112 	break;
   8113       case PTP_OPC_AlbumArtist:
   8114 	// Update album artist
   8115 	ret = set_object_string(device, objecthandle, PTP_OPC_AlbumArtist, artist);
   8116 	if (ret != 0) {
   8117 	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8118 				  "could not set album artist name.");
   8119 	}
   8120 	break;
   8121       case PTP_OPC_Artist:
   8122 	// Update artist
   8123 	ret = set_object_string(device, objecthandle, PTP_OPC_Artist, artist);
   8124 	if (ret != 0) {
   8125 	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8126 				  "could not set artist name.");
   8127 	}
   8128 	break;
   8129       case PTP_OPC_Composer:
   8130 	// Update composer
   8131 	ret = set_object_string(device, objecthandle, PTP_OPC_Composer, composer);
   8132 	if (ret != 0) {
   8133 	  add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8134 				  "could not set composer name.");
   8135 	}
   8136 	break;
   8137       case PTP_OPC_Genre:
   8138 	// Update genre (but only if valid)
   8139 	if(genre) {
   8140 	  ret = set_object_string(device, objecthandle, PTP_OPC_Genre, genre);
   8141 	  if (ret != 0) {
   8142 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8143 				    "could not set genre.");
   8144 	  }
   8145         }
   8146 	break;
   8147       case PTP_OPC_DateModified:
   8148 	// Update date modified
   8149 	if (!FLAG_CANNOT_HANDLE_DATEMODIFIED(ptp_usb)) {
   8150 	  char *tmpdate = get_iso8601_stamp();
   8151 	  ret = set_object_string(device, objecthandle, PTP_OPC_DateModified, tmpdate);
   8152 	  if (ret != 0) {
   8153 	    add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8154 				    "could not set modification date.");
   8155 	  }
   8156 	  free(tmpdate);
   8157 	}
   8158 	break;
   8159       default:
   8160 	break;
   8161       }
   8162     }
   8163   } else {
   8164     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "update_abstract_list(): "
   8165                             "Your device doesn't seem to support any known way of setting metadata.");
   8166     free(properties);
   8167     return -1;
   8168   }
   8169 
   8170   // Then the object references...
   8171   ret = ptp_mtp_setobjectreferences (params, objecthandle, (uint32_t *) tracks, no_tracks);
   8172   if (ret != PTP_RC_OK) {
   8173     add_ptp_error_to_errorstack(device, ret, "update_abstract_list(): could not add tracks as object references.");
   8174     free(properties);
   8175     return -1;
   8176   }
   8177 
   8178   free(properties);
   8179 
   8180   update_metadata_cache(device, objecthandle);
   8181 
   8182   return 0;
   8183 }
   8184 
   8185 
   8186 /**
   8187  * This routine creates a new playlist based on the metadata
   8188  * supplied. If the <code>tracks</code> field of the metadata
   8189  * contains a track listing, these tracks will be added to the
   8190  * playlist.
   8191  * @param device a pointer to the device to create the new playlist on.
   8192  * @param metadata the metadata for the new playlist. If the function
   8193  *        exits with success, the <code>playlist_id</code> field of this
   8194  *        struct will contain the new playlist ID of the playlist.
   8195  *        <ul>
   8196  *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
   8197  *        (e.g. folder) to store this track in. Since some
   8198  *        devices are a bit picky about where files
   8199  *        are placed, a default folder will be chosen if libmtp
   8200  *        has detected one for the current filetype and this
   8201  *        parameter is set to 0. If this is 0 and no default folder
   8202  *        can be found, the file will be stored in the root folder.
   8203  *        <li><code>metadata-&gt;storage_id</code> should be set to the
   8204  *        desired storage (e.g. memory card or whatever your device
   8205  *        presents) to store this track in. Setting this to 0 will store
   8206  *        the track on the primary storage.
   8207  *        </ul>
   8208  * @return 0 on success, any other value means failure.
   8209  * @see LIBMTP_Update_Playlist()
   8210  * @see LIBMTP_Delete_Object()
   8211  */
   8212 int LIBMTP_Create_New_Playlist(LIBMTP_mtpdevice_t *device,
   8213 			       LIBMTP_playlist_t * const metadata)
   8214 {
   8215   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   8216   uint32_t localph = metadata->parent_id;
   8217 
   8218   // Use a default folder if none given
   8219   if (localph == 0) {
   8220     if (device->default_playlist_folder != 0)
   8221       localph = device->default_playlist_folder;
   8222     else
   8223       localph = device->default_music_folder;
   8224   }
   8225   metadata->parent_id = localph;
   8226 
   8227   // Samsung needs its own special type of playlists
   8228   if(FLAG_PLAYLIST_SPL(ptp_usb)) {
   8229     return playlist_t_to_spl(device, metadata);
   8230   }
   8231 
   8232   // Just create a new abstract audio/video playlist...
   8233   return create_new_abstract_list(device,
   8234 				  metadata->name,
   8235 				  NULL,
   8236 				  NULL,
   8237 				  NULL,
   8238 				  localph,
   8239 				  metadata->storage_id,
   8240 				  PTP_OFC_MTP_AbstractAudioVideoPlaylist,
   8241 				  get_playlist_extension(ptp_usb),
   8242 				  &metadata->playlist_id,
   8243 				  metadata->tracks,
   8244 				  metadata->no_tracks);
   8245 }
   8246 
   8247 /**
   8248  * This routine updates a playlist based on the metadata
   8249  * supplied. If the <code>tracks</code> field of the metadata
   8250  * contains a track listing, these tracks will be added to the
   8251  * playlist in place of those already present, i.e. the
   8252  * previous track listing will be deleted. For Samsung devices the
   8253  * playlist id (metadata->playlist_id) is likely to change.
   8254  * @param device a pointer to the device to create the new playlist on.
   8255  * @param metadata the metadata for the playlist to be updated.
   8256  *                 notice that the field <code>playlist_id</code>
   8257  *                 must contain the apropriate playlist ID. Playlist ID
   8258  *                 be modified to a new playlist ID by the time the
   8259  *                 function returns since edit-in-place is not always possible.
   8260  * @return 0 on success, any other value means failure.
   8261  * @see LIBMTP_Create_New_Playlist()
   8262  * @see LIBMTP_Delete_Object()
   8263  */
   8264 int LIBMTP_Update_Playlist(LIBMTP_mtpdevice_t *device,
   8265 			   LIBMTP_playlist_t * const metadata)
   8266 {
   8267 
   8268   // Samsung needs its own special type of playlists
   8269   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   8270   if(FLAG_PLAYLIST_SPL(ptp_usb)) {
   8271     return update_spl_playlist(device, metadata);
   8272   }
   8273 
   8274   return update_abstract_list(device,
   8275 			      metadata->name,
   8276 			      NULL,
   8277 			      NULL,
   8278 			      NULL,
   8279 			      metadata->playlist_id,
   8280 			      PTP_OFC_MTP_AbstractAudioVideoPlaylist,
   8281 			      metadata->tracks,
   8282 			      metadata->no_tracks);
   8283 }
   8284 
   8285 /**
   8286  * This creates a new album metadata structure and allocates memory
   8287  * for it. Notice that if you add strings to this structure they
   8288  * will be freed by the corresponding <code>LIBMTP_destroy_album_t</code>
   8289  * operation later, so be careful of using strdup() when assigning
   8290  * strings.
   8291  *
   8292  * @return a pointer to the newly allocated metadata structure.
   8293  * @see LIBMTP_destroy_album_t()
   8294  */
   8295 LIBMTP_album_t *LIBMTP_new_album_t(void)
   8296 {
   8297   LIBMTP_album_t *new = (LIBMTP_album_t *) malloc(sizeof(LIBMTP_album_t));
   8298   if (new == NULL) {
   8299     return NULL;
   8300   }
   8301   new->album_id = 0;
   8302   new->parent_id = 0;
   8303   new->storage_id = 0;
   8304   new->name = NULL;
   8305   new->artist = NULL;
   8306   new->composer = NULL;
   8307   new->genre = NULL;
   8308   new->tracks = NULL;
   8309   new->no_tracks = 0;
   8310   new->next = NULL;
   8311   return new;
   8312 }
   8313 
   8314 /**
   8315  * This recursively deletes the memory for an album structure
   8316  *
   8317  * @param album structure to destroy
   8318  * @see LIBMTP_new_album_t()
   8319  */
   8320 void LIBMTP_destroy_album_t(LIBMTP_album_t *album)
   8321 {
   8322   if (album == NULL) {
   8323     return;
   8324   }
   8325   if (album->name != NULL)
   8326     free(album->name);
   8327   if (album->artist != NULL)
   8328     free(album->artist);
   8329   if (album->composer != NULL)
   8330     free(album->composer);
   8331   if (album->genre != NULL)
   8332     free(album->genre);
   8333   if (album->tracks != NULL)
   8334     free(album->tracks);
   8335   free(album);
   8336   return;
   8337 }
   8338 
   8339 /**
   8340  * This function maps and copies a property onto the album metadata if applicable.
   8341  */
   8342 static void pick_property_to_album_metadata(LIBMTP_mtpdevice_t *device,
   8343 					    MTPProperties *prop, LIBMTP_album_t *alb)
   8344 {
   8345   switch (prop->property) {
   8346   case PTP_OPC_Name:
   8347     if (prop->propval.str != NULL)
   8348       alb->name = strdup(prop->propval.str);
   8349     else
   8350       alb->name = NULL;
   8351     break;
   8352   case PTP_OPC_AlbumArtist:
   8353     if (prop->propval.str != NULL) {
   8354       // This should take precedence over plain "Artist"
   8355       if (alb->artist != NULL)
   8356 	free(alb->artist);
   8357       alb->artist = strdup(prop->propval.str);
   8358     } else
   8359       alb->artist = NULL;
   8360     break;
   8361   case PTP_OPC_Artist:
   8362     if (prop->propval.str != NULL) {
   8363       // Only use of AlbumArtist is not set
   8364       if (alb->artist == NULL)
   8365 	alb->artist = strdup(prop->propval.str);
   8366     } else
   8367       alb->artist = NULL;
   8368     break;
   8369   case PTP_OPC_Composer:
   8370     if (prop->propval.str != NULL)
   8371       alb->composer = strdup(prop->propval.str);
   8372     else
   8373       alb->composer = NULL;
   8374     break;
   8375   case PTP_OPC_Genre:
   8376     if (prop->propval.str != NULL)
   8377       alb->genre = strdup(prop->propval.str);
   8378     else
   8379       alb->genre = NULL;
   8380     break;
   8381   }
   8382 }
   8383 
   8384 /**
   8385  * This function retrieves the album metadata for an album
   8386  * given by a unique ID.
   8387  * @param device a pointer to the device to get the track metadata off.
   8388  * @param alb an album metadata metadata set to fill in.
   8389  */
   8390 static void get_album_metadata(LIBMTP_mtpdevice_t *device,
   8391 			       LIBMTP_album_t *alb)
   8392 {
   8393   uint16_t ret;
   8394   PTPParams *params = (PTPParams *) device->params;
   8395   uint32_t i;
   8396   MTPProperties *prop;
   8397   PTPObject *ob;
   8398 
   8399   /*
   8400    * If we have a cached, large set of metadata, then use it!
   8401    */
   8402   ret = ptp_object_want(params, alb->album_id, PTPOBJECT_MTPPROPLIST_LOADED, &ob);
   8403   if (ob->mtpprops) {
   8404     prop = ob->mtpprops;
   8405     for (i=0;i<ob->nrofmtpprops;i++,prop++)
   8406       pick_property_to_album_metadata(device, prop, alb);
   8407   } else {
   8408     uint16_t *props = NULL;
   8409     uint32_t propcnt = 0;
   8410 
   8411     // First see which properties can be retrieved for albums
   8412     ret = ptp_mtp_getobjectpropssupported(params, PTP_OFC_MTP_AbstractAudioAlbum, &propcnt, &props);
   8413     if (ret != PTP_RC_OK) {
   8414       add_ptp_error_to_errorstack(device, ret, "get_album_metadata(): call to ptp_mtp_getobjectpropssupported() failed.");
   8415       // Just bail out for now, nothing is ever set.
   8416       return;
   8417     } else {
   8418       for (i=0;i<propcnt;i++) {
   8419 	switch (props[i]) {
   8420 	case PTP_OPC_Name:
   8421 	  alb->name = get_string_from_object(device, ob->oid, PTP_OPC_Name);
   8422 	  break;
   8423 	case PTP_OPC_AlbumArtist:
   8424 	  if (alb->artist != NULL)
   8425 	    free(alb->artist);
   8426 	  alb->artist = get_string_from_object(device, ob->oid, PTP_OPC_AlbumArtist);
   8427 	  break;
   8428 	case PTP_OPC_Artist:
   8429 	  if (alb->artist == NULL)
   8430 	    alb->artist = get_string_from_object(device, ob->oid, PTP_OPC_Artist);
   8431 	  break;
   8432 	case PTP_OPC_Composer:
   8433 	  alb->composer = get_string_from_object(device, ob->oid, PTP_OPC_Composer);
   8434 	  break;
   8435 	case PTP_OPC_Genre:
   8436 	  alb->genre = get_string_from_object(device, ob->oid, PTP_OPC_Genre);
   8437 	  break;
   8438 	default:
   8439 	  break;
   8440 	}
   8441       }
   8442       free(props);
   8443     }
   8444   }
   8445 }
   8446 
   8447 
   8448 /**
   8449  * This function returns a list of the albums available on the
   8450  * device.
   8451  *
   8452  * @param device a pointer to the device to get the album listing from.
   8453  * @return an album list on success, else NULL. If there are no albums
   8454  *         on the device, NULL will be returned as well.
   8455  * @see LIBMTP_Get_Album()
   8456  */
   8457 LIBMTP_album_t *LIBMTP_Get_Album_List(LIBMTP_mtpdevice_t *device)
   8458 {
   8459 	// Read all storage devices
   8460 	return LIBMTP_Get_Album_List_For_Storage(device, 0);
   8461 }
   8462 
   8463 
   8464 /**
   8465  * This function returns a list of the albums available on the
   8466  * device. You can filter on the storage ID.
   8467  *
   8468  * @param device a pointer to the device to get the album listing from.
   8469  * @param storage_id ID of device storage (if null, all storages)
   8470  *
   8471  * @return an album list on success, else NULL. If there are no albums
   8472  *         on the device, NULL will be returned as well.
   8473  * @see LIBMTP_Get_Album()
   8474  */
   8475 LIBMTP_album_t *LIBMTP_Get_Album_List_For_Storage(LIBMTP_mtpdevice_t *device, uint32_t const storage_id)
   8476 {
   8477   PTPParams *params = (PTPParams *) device->params;
   8478   LIBMTP_album_t *retalbums = NULL;
   8479   LIBMTP_album_t *curalbum = NULL;
   8480   uint32_t i;
   8481 
   8482   // Get all the handles if we haven't already done that
   8483   if (params->nrofobjects == 0)
   8484     flush_handles(device);
   8485 
   8486   for (i = 0; i < params->nrofobjects; i++) {
   8487     LIBMTP_album_t *alb;
   8488     PTPObject *ob;
   8489     uint16_t ret;
   8490 
   8491     ob = &params->objects[i];
   8492 
   8493     // Ignore stuff that isn't an album
   8494     if ( ob->oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioAlbum )
   8495       continue;
   8496 
   8497 	// Ignore stuff that isn't into the storage device
   8498 	if ((storage_id != 0) && (ob->oi.StorageID != storage_id ))
   8499 		continue;
   8500 
   8501     // Allocate a new album type
   8502     alb = LIBMTP_new_album_t();
   8503     alb->album_id = ob->oid;
   8504     alb->parent_id = ob->oi.ParentObject;
   8505     alb->storage_id = ob->oi.StorageID;
   8506 
   8507     // Fetch supported metadata
   8508     get_album_metadata(device, alb);
   8509 
   8510     // Then get the track listing for this album
   8511     ret = ptp_mtp_getobjectreferences(params, alb->album_id, &alb->tracks, &alb->no_tracks);
   8512     if (ret != PTP_RC_OK) {
   8513       add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Album_List(): Could not get object references.");
   8514       alb->tracks = NULL;
   8515       alb->no_tracks = 0;
   8516     }
   8517 
   8518     // Add album to a list that will be returned afterwards.
   8519     if (retalbums == NULL) {
   8520       retalbums = alb;
   8521       curalbum = alb;
   8522     } else {
   8523       curalbum->next = alb;
   8524       curalbum = alb;
   8525     }
   8526 
   8527   }
   8528   return retalbums;
   8529 }
   8530 
   8531 /**
   8532  * This function retrieves an individual album from the device.
   8533  * @param device a pointer to the device to get the album from.
   8534  * @param albid the unique ID of the album to retrieve.
   8535  * @return a valid album metadata or NULL on failure.
   8536  * @see LIBMTP_Get_Album_List()
   8537  */
   8538 LIBMTP_album_t *LIBMTP_Get_Album(LIBMTP_mtpdevice_t *device, uint32_t const albid)
   8539 {
   8540   PTPParams *params = (PTPParams *) device->params;
   8541   uint16_t ret;
   8542   PTPObject *ob;
   8543   LIBMTP_album_t *alb;
   8544 
   8545   // Get all the handles if we haven't already done that
   8546   if (params->nrofobjects == 0)
   8547     flush_handles(device);
   8548 
   8549   ret = ptp_object_want(params, albid, PTPOBJECT_OBJECTINFO_LOADED, &ob);
   8550   if (ret != PTP_RC_OK)
   8551     return NULL;
   8552 
   8553   // Ignore stuff that isn't an album
   8554   if (ob->oi.ObjectFormat != PTP_OFC_MTP_AbstractAudioAlbum)
   8555     return NULL;
   8556 
   8557   // Allocate a new album type
   8558   alb = LIBMTP_new_album_t();
   8559   alb->album_id = ob->oid;
   8560   alb->parent_id = ob->oi.ParentObject;
   8561   alb->storage_id = ob->oi.StorageID;
   8562 
   8563   // Fetch supported metadata
   8564   get_album_metadata(device, alb);
   8565 
   8566   // Then get the track listing for this album
   8567   ret = ptp_mtp_getobjectreferences(params, alb->album_id, &alb->tracks, &alb->no_tracks);
   8568   if (ret != PTP_RC_OK) {
   8569     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Album: Could not get object references.");
   8570     alb->tracks = NULL;
   8571     alb->no_tracks = 0;
   8572   }
   8573 
   8574   return alb;
   8575 }
   8576 
   8577 /**
   8578  * This routine creates a new album based on the metadata
   8579  * supplied. If the <code>tracks</code> field of the metadata
   8580  * contains a track listing, these tracks will be added to the
   8581  * album.
   8582  * @param device a pointer to the device to create the new album on.
   8583  * @param metadata the metadata for the new album. If the function
   8584  *        exits with success, the <code>album_id</code> field of this
   8585  *        struct will contain the new ID of the album.
   8586  *        <ul>
   8587  *        <li><code>metadata-&gt;parent_id</code> should be set to the parent
   8588  *        (e.g. folder) to store this track in. Since some
   8589  *        devices are a bit picky about where files
   8590  *        are placed, a default folder will be chosen if libmtp
   8591  *        has detected one for the current filetype and this
   8592  *        parameter is set to 0. If this is 0 and no default folder
   8593  *        can be found, the file will be stored in the root folder.
   8594  *        <li><code>metadata-&gt;storage_id</code> should be set to the
   8595  *        desired storage (e.g. memory card or whatever your device
   8596  *        presents) to store this track in. Setting this to 0 will store
   8597  *        the track on the primary storage.
   8598  *        </ul>
   8599  * @return 0 on success, any other value means failure.
   8600  * @see LIBMTP_Update_Album()
   8601  * @see LIBMTP_Delete_Object()
   8602  */
   8603 int LIBMTP_Create_New_Album(LIBMTP_mtpdevice_t *device,
   8604 			    LIBMTP_album_t * const metadata)
   8605 {
   8606   uint32_t localph = metadata->parent_id;
   8607 
   8608   // Use a default folder if none given
   8609   if (localph == 0) {
   8610     if (device->default_album_folder != 0)
   8611       localph = device->default_album_folder;
   8612     else
   8613       localph = device->default_music_folder;
   8614   }
   8615   metadata->parent_id = localph;
   8616 
   8617   // Just create a new abstract album...
   8618   return create_new_abstract_list(device,
   8619 				  metadata->name,
   8620 				  metadata->artist,
   8621 				  metadata->composer,
   8622 				  metadata->genre,
   8623 				  localph,
   8624 				  metadata->storage_id,
   8625 				  PTP_OFC_MTP_AbstractAudioAlbum,
   8626 				  ".alb",
   8627 				  &metadata->album_id,
   8628 				  metadata->tracks,
   8629 				  metadata->no_tracks);
   8630 }
   8631 
   8632 /**
   8633  * This creates a new sample data metadata structure and allocates memory
   8634  * for it. Notice that if you add strings to this structure they
   8635  * will be freed by the corresponding <code>LIBMTP_destroy_sampledata_t</code>
   8636  * operation later, so be careful of using strdup() when assigning
   8637  * strings.
   8638  *
   8639  * @return a pointer to the newly allocated metadata structure.
   8640  * @see LIBMTP_destroy_sampledata_t()
   8641  */
   8642 LIBMTP_filesampledata_t *LIBMTP_new_filesampledata_t(void)
   8643 {
   8644   LIBMTP_filesampledata_t *new = (LIBMTP_filesampledata_t *) malloc(sizeof(LIBMTP_filesampledata_t));
   8645   if (new == NULL) {
   8646     return NULL;
   8647   }
   8648   new->height=0;
   8649   new->width = 0;
   8650   new->data = NULL;
   8651   new->duration = 0;
   8652   new->size = 0;
   8653   return new;
   8654 }
   8655 
   8656 /**
   8657  * This destroys a file sample metadata type.
   8658  * @param sample the file sample metadata to be destroyed.
   8659  */
   8660 void LIBMTP_destroy_filesampledata_t(LIBMTP_filesampledata_t * sample)
   8661 {
   8662   if (sample == NULL) {
   8663     return;
   8664   }
   8665   if (sample->data != NULL) {
   8666     free(sample->data);
   8667   }
   8668   free(sample);
   8669 }
   8670 
   8671 /**
   8672  * This routine figures out whether a certain filetype supports
   8673  * representative samples (small thumbnail images) or not. This
   8674  * typically applies to JPEG files, MP3 files and Album abstract
   8675  * playlists, but in theory any filetype could support representative
   8676  * samples.
   8677  * @param device a pointer to the device which is to be examined.
   8678  * @param filetype the fileype to examine, and return the representative sample
   8679  *        properties for.
   8680  * @param sample this will contain a new sample type with the fields
   8681  *        filled in with suitable default values. For example, the
   8682  *        supported sample type will be set, the supported height and
   8683  *        width will be set to max values if it is an image sample,
   8684  *        and duration will also be given some suitable default value
   8685  *        which should not be exceeded on audio samples. If the
   8686  *        device does not support samples for this filetype, this
   8687  *        pointer will be NULL. If it is not NULL, the user must
   8688  *        destroy this struct with <code>LIBMTP_destroy_filesampledata_t()</code>
   8689  *        after use.
   8690  * @return 0 on success, any other value means failure.
   8691  * @see LIBMTP_Send_Representative_Sample()
   8692  * @see LIBMTP_Create_New_Album()
   8693  */
   8694 int LIBMTP_Get_Representative_Sample_Format(LIBMTP_mtpdevice_t *device,
   8695 					    LIBMTP_filetype_t const filetype,
   8696 					    LIBMTP_filesampledata_t ** sample)
   8697 {
   8698   uint16_t ret;
   8699   PTPParams *params = (PTPParams *) device->params;
   8700   uint16_t *props = NULL;
   8701   uint32_t propcnt = 0;
   8702   int i;
   8703   // TODO: Get rid of these when we can properly query the device.
   8704   int support_data = 0;
   8705   int support_format = 0;
   8706   int support_height = 0;
   8707   int support_width = 0;
   8708   int support_duration = 0;
   8709   int support_size = 0;
   8710 
   8711   PTPObjectPropDesc opd_height;
   8712   PTPObjectPropDesc opd_width;
   8713   PTPObjectPropDesc opd_format;
   8714   PTPObjectPropDesc opd_duration;
   8715   PTPObjectPropDesc opd_size;
   8716 
   8717   // Default to no type supported.
   8718   *sample = NULL;
   8719 
   8720   ret = ptp_mtp_getobjectpropssupported(params, map_libmtp_type_to_ptp_type(filetype), &propcnt, &props);
   8721   if (ret != PTP_RC_OK) {
   8722     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Representative_Sample_Format(): could not get object properties.");
   8723     return -1;
   8724   }
   8725   /*
   8726    * TODO: when walking through these object properties, make calls to
   8727    * a new function in ptp.h/ptp.c that can send the command
   8728    * PTP_OC_MTP_GetObjectPropDesc to get max/min values of the properties
   8729    * supported.
   8730    */
   8731   for (i = 0; i < propcnt; i++) {
   8732     switch(props[i]) {
   8733     case PTP_OPC_RepresentativeSampleData:
   8734       support_data = 1;
   8735       break;
   8736     case PTP_OPC_RepresentativeSampleFormat:
   8737       support_format = 1;
   8738       break;
   8739     case PTP_OPC_RepresentativeSampleSize:
   8740       support_size = 1;
   8741       break;
   8742     case PTP_OPC_RepresentativeSampleHeight:
   8743       support_height = 1;
   8744       break;
   8745     case PTP_OPC_RepresentativeSampleWidth:
   8746       support_width = 1;
   8747       break;
   8748     case PTP_OPC_RepresentativeSampleDuration:
   8749       support_duration = 1;
   8750       break;
   8751     default:
   8752       break;
   8753     }
   8754   }
   8755   free(props);
   8756 
   8757   if (support_data && support_format && support_height && support_width && !support_duration) {
   8758     // Something that supports height and width and not duration is likely to be JPEG
   8759     LIBMTP_filesampledata_t *retsam = LIBMTP_new_filesampledata_t();
   8760     /*
   8761      * Populate the sample format with the first supported format
   8762      *
   8763      * TODO: figure out how to pass back more than one format if more are
   8764      * supported by the device.
   8765      */
   8766     ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleFormat, map_libmtp_type_to_ptp_type(filetype), &opd_format);
   8767     retsam->filetype = map_ptp_type_to_libmtp_type(opd_format.FORM.Enum.SupportedValue[0].u16);
   8768     ptp_free_objectpropdesc(&opd_format);
   8769     /* Populate the maximum image height */
   8770     ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleWidth, map_libmtp_type_to_ptp_type(filetype), &opd_width);
   8771     retsam->width = opd_width.FORM.Range.MaximumValue.u32;
   8772     ptp_free_objectpropdesc(&opd_width);
   8773     /* Populate the maximum image width */
   8774     ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleHeight, map_libmtp_type_to_ptp_type(filetype), &opd_height);
   8775     retsam->height = opd_height.FORM.Range.MaximumValue.u32;
   8776     ptp_free_objectpropdesc(&opd_height);
   8777     /* Populate the maximum size */
   8778     if (support_size) {
   8779       ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleSize, map_libmtp_type_to_ptp_type(filetype), &opd_size);
   8780       retsam->size = opd_size.FORM.Range.MaximumValue.u32;
   8781       ptp_free_objectpropdesc(&opd_size);
   8782     }
   8783     *sample = retsam;
   8784   } else if (support_data && support_format && !support_height && !support_width && support_duration) {
   8785     // Another qualified guess
   8786     LIBMTP_filesampledata_t *retsam = LIBMTP_new_filesampledata_t();
   8787     /*
   8788      * Populate the sample format with the first supported format
   8789      *
   8790      * TODO: figure out how to pass back more than one format if more are
   8791      * supported by the device.
   8792      */
   8793     ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleFormat, map_libmtp_type_to_ptp_type(filetype), &opd_format);
   8794     retsam->filetype = map_ptp_type_to_libmtp_type(opd_format.FORM.Enum.SupportedValue[0].u16);
   8795     ptp_free_objectpropdesc(&opd_format);
   8796     /* Populate the maximum duration */
   8797     ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleDuration, map_libmtp_type_to_ptp_type(filetype), &opd_duration);
   8798     retsam->duration = opd_duration.FORM.Range.MaximumValue.u32;
   8799     ptp_free_objectpropdesc(&opd_duration);
   8800     /* Populate the maximum size */
   8801     if (support_size) {
   8802       ptp_mtp_getobjectpropdesc (params, PTP_OPC_RepresentativeSampleSize, map_libmtp_type_to_ptp_type(filetype), &opd_size);
   8803       retsam->size = opd_size.FORM.Range.MaximumValue.u32;
   8804       ptp_free_objectpropdesc(&opd_size);
   8805     }
   8806     *sample = retsam;
   8807   }
   8808   return 0;
   8809 }
   8810 
   8811 /**
   8812  * This routine sends representative sample data for an object.
   8813  * This uses the RepresentativeSampleData property of the album,
   8814  * if the device supports it. The data should be of a format acceptable
   8815  * to the player (for iRiver and Creative, this seems to be JPEG) and
   8816  * must not be too large. (for a Creative, max seems to be about 20KB.)
   8817  * Check by calling LIBMTP_Get_Representative_Sample_Format() to get
   8818  * maximum size, dimensions, etc..
   8819  * @param device a pointer to the device which the object is on.
   8820  * @param id unique id of the object to set artwork for.
   8821  * @param pointer to LIBMTP_filesampledata_t struct containing data
   8822  * @return 0 on success, any other value means failure.
   8823  * @see LIBMTP_Get_Representative_Sample()
   8824  * @see LIBMTP_Get_Representative_Sample_Format()
   8825  * @see LIBMTP_Create_New_Album()
   8826  */
   8827 int LIBMTP_Send_Representative_Sample(LIBMTP_mtpdevice_t *device,
   8828                           uint32_t const id,
   8829                           LIBMTP_filesampledata_t *sampledata)
   8830 {
   8831   uint16_t ret;
   8832   PTPParams *params = (PTPParams *) device->params;
   8833   PTP_USB *ptp_usb = (PTP_USB*) device->usbinfo;
   8834   PTPPropertyValue propval;
   8835   PTPObject *ob;
   8836   uint32_t i;
   8837   uint16_t *props = NULL;
   8838   uint32_t propcnt = 0;
   8839   int supported = 0;
   8840 
   8841   // get the file format for the object we're going to send representative data for
   8842   ret = ptp_object_want (params, id, PTPOBJECT_OBJECTINFO_LOADED, &ob);
   8843   if (ret != PTP_RC_OK) {
   8844     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_Representative_Sample(): could not get object info.");
   8845     return -1;
   8846   }
   8847 
   8848   // check that we can send representative sample data for this object format
   8849   ret = ptp_mtp_getobjectpropssupported(params, ob->oi.ObjectFormat, &propcnt, &props);
   8850   if (ret != PTP_RC_OK) {
   8851     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_Representative_Sample(): could not get object properties.");
   8852     return -1;
   8853   }
   8854 
   8855   for (i = 0; i < propcnt; i++) {
   8856     if (props[i] == PTP_OPC_RepresentativeSampleData) {
   8857       supported = 1;
   8858       break;
   8859     }
   8860   }
   8861   if (!supported) {
   8862     free(props);
   8863     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Send_Representative_Sample(): object type doesn't support RepresentativeSampleData.");
   8864     return -1;
   8865   }
   8866   free(props);
   8867 
   8868   // Go ahead and send the data
   8869   propval.a.count = sampledata->size;
   8870   propval.a.v = malloc(sizeof(PTPPropertyValue) * sampledata->size);
   8871   for (i = 0; i < sampledata->size; i++) {
   8872     propval.a.v[i].u8 = sampledata->data[i];
   8873   }
   8874 
   8875   ret = ptp_mtp_setobjectpropvalue(params,id,PTP_OPC_RepresentativeSampleData,
   8876 				   &propval,PTP_DTC_AUINT8);
   8877   if (ret != PTP_RC_OK) {
   8878     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Send_Representative_Sample(): could not send sample data.");
   8879     free(propval.a.v);
   8880     return -1;
   8881   }
   8882   free(propval.a.v);
   8883 
   8884   /* Set the height and width if the sample is an image, otherwise just
   8885    * set the duration and size */
   8886   switch(sampledata->filetype) {
   8887   case LIBMTP_FILETYPE_JPEG:
   8888   case LIBMTP_FILETYPE_JFIF:
   8889   case LIBMTP_FILETYPE_TIFF:
   8890   case LIBMTP_FILETYPE_BMP:
   8891   case LIBMTP_FILETYPE_GIF:
   8892   case LIBMTP_FILETYPE_PICT:
   8893   case LIBMTP_FILETYPE_PNG:
   8894     if (!FLAG_BROKEN_SET_SAMPLE_DIMENSIONS(ptp_usb)) {
   8895       // For images, set the height and width
   8896       set_object_u32(device, id, PTP_OPC_RepresentativeSampleHeight, sampledata->height);
   8897       set_object_u32(device, id, PTP_OPC_RepresentativeSampleWidth, sampledata->width);
   8898     }
   8899     break;
   8900   default:
   8901     // For anything not an image, set the duration and size
   8902     set_object_u32(device, id, PTP_OPC_RepresentativeSampleDuration, sampledata->duration);
   8903     set_object_u32(device, id, PTP_OPC_RepresentativeSampleSize, sampledata->size);
   8904     break;
   8905   }
   8906 
   8907   return 0;
   8908 }
   8909 
   8910 /**
   8911  * This routine gets representative sample data for an object.
   8912  * This uses the RepresentativeSampleData property of the album,
   8913  * if the device supports it.
   8914  * @param device a pointer to the device which the object is on.
   8915  * @param id unique id of the object to get data for.
   8916  * @param pointer to LIBMTP_filesampledata_t struct to receive data
   8917  * @return 0 on success, any other value means failure.
   8918  * @see LIBMTP_Send_Representative_Sample()
   8919  * @see LIBMTP_Get_Representative_Sample_Format()
   8920  * @see LIBMTP_Create_New_Album()
   8921  */
   8922 int LIBMTP_Get_Representative_Sample(LIBMTP_mtpdevice_t *device,
   8923                           uint32_t const id,
   8924                           LIBMTP_filesampledata_t *sampledata)
   8925 {
   8926   uint16_t ret;
   8927   PTPParams *params = (PTPParams *) device->params;
   8928   PTPPropertyValue propval;
   8929   PTPObject *ob;
   8930   uint32_t i;
   8931   uint16_t *props = NULL;
   8932   uint32_t propcnt = 0;
   8933   int supported = 0;
   8934 
   8935   // get the file format for the object we're going to send representative data for
   8936   ret = ptp_object_want (params, id, PTPOBJECT_OBJECTINFO_LOADED, &ob);
   8937   if (ret != PTP_RC_OK) {
   8938     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_Representative_Sample(): could not get object info.");
   8939     return -1;
   8940   }
   8941 
   8942   // check that we can store representative sample data for this object format
   8943   ret = ptp_mtp_getobjectpropssupported(params, ob->oi.ObjectFormat, &propcnt, &props);
   8944   if (ret != PTP_RC_OK) {
   8945     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Representative_Sample(): could not get object properties.");
   8946     return -1;
   8947   }
   8948 
   8949   for (i = 0; i < propcnt; i++) {
   8950     if (props[i] == PTP_OPC_RepresentativeSampleData) {
   8951       supported = 1;
   8952       break;
   8953     }
   8954   }
   8955   if (!supported) {
   8956     free(props);
   8957     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL, "LIBMTP_Get_Representative_Sample(): object type doesn't support RepresentativeSampleData.");
   8958     return -1;
   8959   }
   8960   free(props);
   8961 
   8962   // Get the data
   8963   ret = ptp_mtp_getobjectpropvalue(params,id,PTP_OPC_RepresentativeSampleData,
   8964 				   &propval,PTP_DTC_AUINT8);
   8965   if (ret != PTP_RC_OK) {
   8966     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Get_Representative_Sample(): could not get sample data.");
   8967     return -1;
   8968   }
   8969 
   8970   // Store it
   8971   sampledata->size = propval.a.count;
   8972   sampledata->data = malloc(sizeof(PTPPropertyValue) * propval.a.count);
   8973   for (i = 0; i < propval.a.count; i++) {
   8974     sampledata->data[i] = propval.a.v[i].u8;
   8975   }
   8976   free(propval.a.v);
   8977 
   8978   // Get the other properties
   8979   sampledata->width = get_u32_from_object(device, id, PTP_OPC_RepresentativeSampleWidth, 0);
   8980   sampledata->height = get_u32_from_object(device, id, PTP_OPC_RepresentativeSampleHeight, 0);
   8981   sampledata->duration = get_u32_from_object(device, id, PTP_OPC_RepresentativeSampleDuration, 0);
   8982   sampledata->filetype = map_ptp_type_to_libmtp_type(
   8983         get_u16_from_object(device, id, PTP_OPC_RepresentativeSampleFormat, LIBMTP_FILETYPE_UNKNOWN));
   8984 
   8985   return 0;
   8986 }
   8987 
   8988 /**
   8989  * Retrieve the thumbnail for a file.
   8990  * @param device a pointer to the device to get the thumbnail from.
   8991  * @param id the object ID of the file to retrieve the thumbnail for.
   8992  * @return 0 on success, any other value means failure.
   8993  */
   8994 int LIBMTP_Get_Thumbnail(LIBMTP_mtpdevice_t *device, uint32_t const id,
   8995                          unsigned char **data, unsigned int *size)
   8996 {
   8997   PTPParams *params = (PTPParams *) device->params;
   8998   uint16_t ret;
   8999 
   9000   ret = ptp_getthumb(params, id, data, size);
   9001   if (ret == PTP_RC_OK)
   9002       return 0;
   9003   return -1;
   9004 }
   9005 
   9006 
   9007 int LIBMTP_GetPartialObject(LIBMTP_mtpdevice_t *device, uint32_t const id,
   9008                             uint64_t offset, uint32_t maxbytes,
   9009                             unsigned char **data, unsigned int *size)
   9010 {
   9011   PTPParams *params = (PTPParams *) device->params;
   9012   uint16_t ret;
   9013 
   9014   if (!ptp_operation_issupported(params, PTP_OC_ANDROID_GetPartialObject64)) {
   9015     if  (!ptp_operation_issupported(params, PTP_OC_GetPartialObject)) {
   9016       add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   9017         "LIBMTP_GetPartialObject: PTP_OC_GetPartialObject not supported");
   9018       return -1;
   9019     }
   9020 
   9021     if (offset >> 32 != 0) {
   9022       add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   9023         "LIBMTP_GetPartialObject: PTP_OC_GetPartialObject only supports 32bit offsets");
   9024       return -1;
   9025     }
   9026 
   9027     ret = ptp_getpartialobject(params, id, (uint32_t)offset, maxbytes, data, size);
   9028   } else {
   9029     ret = ptp_android_getpartialobject64(params, id, offset, maxbytes, data, size);
   9030   }
   9031   if (ret == PTP_RC_OK)
   9032       return 0;
   9033   return -1;
   9034 }
   9035 
   9036 
   9037 int LIBMTP_SendPartialObject(LIBMTP_mtpdevice_t *device, uint32_t const id,
   9038                              uint64_t offset, unsigned char *data, unsigned int size)
   9039 {
   9040   PTPParams *params = (PTPParams *) device->params;
   9041   uint16_t ret;
   9042 
   9043   if (!ptp_operation_issupported(params, PTP_OC_ANDROID_SendPartialObject)) {
   9044     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   9045       "LIBMTP_SendPartialObject: PTP_OC_ANDROID_SendPartialObject not supported");
   9046     return -1;
   9047   }
   9048 
   9049   ret = ptp_android_sendpartialobject(params, id, offset, data, size);
   9050   if (ret == PTP_RC_OK)
   9051       return 0;
   9052   return -1;
   9053 }
   9054 
   9055 
   9056 int LIBMTP_BeginEditObject(LIBMTP_mtpdevice_t *device, uint32_t const id)
   9057 {
   9058   PTPParams *params = (PTPParams *) device->params;
   9059   uint16_t ret;
   9060 
   9061   if (!ptp_operation_issupported(params, PTP_OC_ANDROID_BeginEditObject)) {
   9062     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   9063       "LIBMTP_BeginEditObject: PTP_OC_ANDROID_BeginEditObject not supported");
   9064     return -1;
   9065   }
   9066 
   9067   ret = ptp_android_begineditobject(params, id);
   9068   if (ret == PTP_RC_OK)
   9069       return 0;
   9070   return -1;
   9071 }
   9072 
   9073 
   9074 int LIBMTP_EndEditObject(LIBMTP_mtpdevice_t *device, uint32_t const id)
   9075 {
   9076   PTPParams *params = (PTPParams *) device->params;
   9077   uint16_t ret;
   9078 
   9079   if (!ptp_operation_issupported(params, PTP_OC_ANDROID_EndEditObject)) {
   9080     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   9081       "LIBMTP_EndEditObject: PTP_OC_ANDROID_EndEditObject not supported");
   9082     return -1;
   9083   }
   9084 
   9085   ret = ptp_android_endeditobject(params, id);
   9086   if (ret == PTP_RC_OK) {
   9087       // update cached object properties if metadata cache exists
   9088       update_metadata_cache(device, id);
   9089       return 0;
   9090   }
   9091   return -1;
   9092 }
   9093 
   9094 
   9095 int LIBMTP_TruncateObject(LIBMTP_mtpdevice_t *device, uint32_t const id,
   9096                           uint64_t offset)
   9097 {
   9098   PTPParams *params = (PTPParams *) device->params;
   9099   uint16_t ret;
   9100 
   9101   if (!ptp_operation_issupported(params, PTP_OC_ANDROID_TruncateObject)) {
   9102     add_error_to_errorstack(device, LIBMTP_ERROR_GENERAL,
   9103       "LIBMTP_TruncateObject: PTP_OC_ANDROID_TruncateObject not supported");
   9104     return -1;
   9105   }
   9106 
   9107   ret = ptp_android_truncate(params, id, offset);
   9108   if (ret == PTP_RC_OK)
   9109       return 0;
   9110   return -1;
   9111 }
   9112 
   9113 
   9114 /**
   9115  * This routine updates an album based on the metadata
   9116  * supplied. If the <code>tracks</code> field of the metadata
   9117  * contains a track listing, these tracks will be added to the
   9118  * album in place of those already present, i.e. the
   9119  * previous track listing will be deleted.
   9120  * @param device a pointer to the device to create the new album on.
   9121  * @param metadata the metadata for the album to be updated.
   9122  *                 notice that the field <code>album_id</code>
   9123  *                 must contain the apropriate album ID.
   9124  * @return 0 on success, any other value means failure.
   9125  * @see LIBMTP_Create_New_Album()
   9126  * @see LIBMTP_Delete_Object()
   9127  */
   9128 int LIBMTP_Update_Album(LIBMTP_mtpdevice_t *device,
   9129 			   LIBMTP_album_t const * const metadata)
   9130 {
   9131   return update_abstract_list(device,
   9132 			      metadata->name,
   9133 			      metadata->artist,
   9134 			      metadata->composer,
   9135 			      metadata->genre,
   9136 			      metadata->album_id,
   9137 			      PTP_OFC_MTP_AbstractAudioAlbum,
   9138 			      metadata->tracks,
   9139 			      metadata->no_tracks);
   9140 }
   9141 
   9142 /**
   9143  * Dummy function needed to interface to upstream
   9144  * ptp.c/ptp.h files.
   9145  */
   9146 void ptp_nikon_getptpipguid (unsigned char* guid) {
   9147   return;
   9148 }
   9149 
   9150 /**
   9151  * Add an object to cache.
   9152  * @param device the device which may have a cache to which the object should be added.
   9153  * @param object_id the object to add to the cache.
   9154  */
   9155 static void add_object_to_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id)
   9156 {
   9157   PTPParams *params = (PTPParams *)device->params;
   9158   uint16_t ret;
   9159 
   9160   ret = ptp_add_object_to_cache(params, object_id);
   9161   if (ret != PTP_RC_OK) {
   9162     add_ptp_error_to_errorstack(device, ret, "add_object_to_cache(): couldn't add object to cache");
   9163   }
   9164 }
   9165 
   9166 
   9167 /**
   9168  * Update cache after object has been modified
   9169  * @param device the device which may have a cache to which the object should be updated.
   9170  * @param object_id the object to update.
   9171  */
   9172 static void update_metadata_cache(LIBMTP_mtpdevice_t *device, uint32_t object_id)
   9173 {
   9174   PTPParams *params = (PTPParams *)device->params;
   9175 
   9176   ptp_remove_object_from_cache(params, object_id);
   9177   add_object_to_cache(device, object_id);
   9178 }
   9179 
   9180 
   9181 /**
   9182  * Issue custom (e.g. vendor specific) operation (without data phase)
   9183  * @param device a pointer to the device to send custom operation to.
   9184  * @param code operation code to send.
   9185  * @param n_param number of parameters passed.
   9186  * @param ... uint32_t operation specific parameters.
   9187  */
   9188 int LIBMTP_Custom_Operation(LIBMTP_mtpdevice_t *device, uint16_t code, int n_param, ...)
   9189 {
   9190   PTPParams *params = (PTPParams *) device->params;
   9191   PTPContainer ptp;
   9192   va_list args;
   9193   uint16_t ret;
   9194   int i;
   9195 
   9196   ptp.Code = code;
   9197   ptp.Nparam = n_param;
   9198   va_start(args, n_param);
   9199   for (i = 0; i < n_param; i++)
   9200     (&ptp.Param1)[i] = va_arg(args, uint32_t);
   9201   va_end(args);
   9202 
   9203   ret = ptp_transaction_new(params, &ptp, PTP_DP_NODATA, 0, NULL);
   9204 
   9205   if (ret != PTP_RC_OK) {
   9206     add_ptp_error_to_errorstack(device, ret, "LIBMTP_Custom_Operation(): failed to execute operation.");
   9207     return -1;
   9208   }
   9209 
   9210   return 0;
   9211 }
   9212