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 ¤t_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, ¶m1); 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(¶ms->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 ¤tHandles); 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 (¶ms->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 = ¶ms->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->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->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 = ¶ms->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 ¤tHandles); 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 = ¶ms->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->item_id</code> 5473 * will contain the new track ID. Other fields such 5474 * as the <code>metadata->filename</code>, <code>metadata->parent_id</code> 5475 * or <code>metadata->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->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->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->item_id</code> 5606 * will contain the new track ID. Other fields such 5607 * as the <code>metadata->filename</code>, <code>metadata->parent_id</code> 5608 * or <code>metadata->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->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->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->item_id</code> 5710 * will contain the new track ID. Other fields such 5711 * as the <code>metadata->filename</code>, <code>metadata->parent_id</code> 5712 * or <code>metadata->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->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->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->item_id</code> 5813 * will contain the new file ID. Other fields such 5814 * as the <code>filedata->filename</code>, <code>filedata->parent_id</code> 5815 * or <code>filedata->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->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->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->item_id</code> 5890 * will contain the new file ID. Other fields such 5891 * as the <code>filedata->filename</code>, <code>filedata->parent_id</code> 5892 * or <code>filedata->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->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->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->item_id</code> 6007 * will contain the new file ID. Other fields such 6008 * as the <code>filedata->filename</code>, <code>filedata->parent_id</code> 6009 * or <code>filedata->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->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->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 = ¶ms->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 = ¶ms->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->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->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 = ¶ms->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->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->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